使用Scrapy(Python)进行Web数据抓取(在线新闻评论)

使用Scrapy(Python)进行Web数据抓取(在线新闻评论),python,web-scraping,scrapy,Python,Web Scraping,Scrapy,我想纯粹为了研究而从在线新闻中搜集网络评论数据。我注意到我必须学习刮皮 通常,我用Python编程。我想这很容易学。但我有一些问题 我想加入新闻评论 但问题是有一个按钮(>查看评论(452))来查看评论。此外,我想做的是删除该新闻中的所有评论。不幸的是,我不得不点击另一个按钮(查看更多评论)来查看其他10条评论 我如何处理这个问题 我所做的代码如下。对不起,代码太差了 ############################################# from scrapy.spider

我想纯粹为了研究而从在线新闻中搜集网络评论数据。我注意到我必须学习刮皮

通常,我用Python编程。我想这很容易学。但我有一些问题

我想加入新闻评论

但问题是有一个按钮(>查看评论(452))来查看评论。此外,我想做的是删除该新闻中的所有评论。不幸的是,我不得不点击另一个按钮(查看更多评论)来查看其他10条评论

我如何处理这个问题

我所做的代码如下。对不起,代码太差了

#############################################
from scrapy.spider import BaseSpider
from scrapy.selector import Selector
from tutorial.items import DmozItem

class DmozSpider(BaseSpider):
   name = "dmoz"
   allowed_domains = ["news.yahoo.com"]

   start_urls = ["http://news.yahoo.com/blogs/oddnews/driver-offended-by-%E2%80%9Cwh0-r8x%E2`%80%9D-license-plate-221720503.html",]

   def parse(self, response):
       sel = Selector(response)
       sites = sel.xpath('//div/p')
       items = []
       for site in sites:
           item = DmozItem()
           item['title'] = site.xpath('/text()').extract()
           items.append(item)
       return items  

你可以看到,要解决我的问题还有多少工作要做。但是我得快点。。无论如何,我会尽力的

因为你看起来像是“先尝试后提问”类型的人(这是一件非常好的事情),所以我不会给你答案,而是给你一个(非常详细的)如何找到答案的指南

问题是,除非你是一名雅虎开发人员,否则你可能无法访问你试图获取的源代码。也就是说,您不知道站点是如何构建的,也不知道您作为用户对它的请求在服务器端是如何处理的。但是,您可以调查客户端并尝试模拟它。我喜欢使用Chrome开发工具来实现这一点,但您可以使用其他工具,如FF firebug

所以首先我们需要弄清楚到底发生了什么。因此,它的工作方式是,你点击它加载前十条的“显示评论”,然后你需要每次点击下十条评论。然而,请注意,所有这些点击并没有将您带到不同的链接,而是lively获取评论,这是一个非常整洁的UI,但对于我们的案例,需要做更多的工作。我可以马上告诉你两件事:

  • 他们使用javascript加载注释(因为我停留在同一页面上)
  • 每次单击时,它们都会通过AJAX调用动态地加载注释(这意味着,每次单击都会向数据库发出另一个请求,而不是在页面中加载注释并向您显示注释)
  • 现在让我们右键单击并检查该按钮上的元素。实际上,这只是一个简单的文本跨度:

    <span>View Comments (2077)</span>
    
    看到了吗?然后得到你的评论。这很有道理。通过浏览器中的链接,我得到了一个JSON对象(看起来像python字典),其中包含该请求获取的所有十条注释。现在,这是您需要模拟的请求,因为这是为您提供所需内容的请求。首先,让我们将其转化为人类可以阅读的一些普通需求:

    go to this url: http://news.yahoo.com/_xhr/contentcomments/get_comments/
    include these parameters: {'_device': 'full',
              '_media.modules.content_comments.switches._enable_mutecommenter': '1',
              '_media.modules.content_comments.switches._enable_view_others': '1',
              'content_id': '42f7f6e0-7bae-33d3-aa1d-3dfc7fb5cdfc',
              'count': '10',
              'enable_collapsed_comment': '1',
              'isNext': 'true',
              'offset': '20',
              'pageNumber': '2',
              'sortBy': 'highestRated'}
    
    现在这只是一个试错的问题。但是,这里需要注意以下几点:

  • 显然,数量决定了你得到多少评论。我试着把它改为100,看看会发生什么,但收到了一个错误的请求。它很好地告诉了我为什么-“偏移量应该是总行数的倍数”。现在我们了解了如何使用偏移量

  • 内容id可能是标识您正在阅读的文章的内容。这意味着你需要从原始页面获取这些信息。试着四处挖掘一下,你会发现的

  • 此外,您显然不希望一次获取10条评论,因此,以某种方式获取总评论数可能是一个好主意(要么了解页面是如何获取的,要么只是从文章本身中获取)

  • 使用devtools,您可以访问所有客户端脚本。因此,通过挖掘,您可以发现/get_comments/的链接保存在名为YUI的javascript对象中。然后,您可以尝试理解它是如何发出请求的,并尝试模仿它(尽管您自己可能会找到答案)

  • 您可能需要克服一些安全措施。例如,在访问注释之前,您可能需要原始文章中的会话密钥。这用于防止直接访问网站的某些部分。我不会用细节来麻烦你,因为在这种情况下这似乎不是一个问题,但你确实需要意识到这一点,以防它出现

  • 最后,您必须解析JSON对象(python有很好的内置工具),然后解析您得到的html注释(您可能想查看这些注释)

  • 正如你所看到的,这将需要一些工作,但尽管我写了这么多,这也不是一个非常复杂的任务

    所以不要惊慌

    这只是一个不断挖掘的问题,直到你找到金子为止(同时,拥有一些基本的网络知识也没有坏处)。然后,如果你面临一个路障,真的不能再往前走了,回到这里再问一次。有人会帮助你的


    祝你好运

    我很感谢这个问题,因为它让我开始尝试收集雅虎的评论,我只想添加一个更新,因为自从这个问题发布以来,雅虎已经改变了他们处理评论的方式。首先,有3个感兴趣的URL,这取决于你想要得到什么。通过这些,您可以获得主评论线程、对线程的回复或用户的评论。这些是

    urlComments = 'https://www.yahoo.com/news/_td/api/resource/canvass.getMessageListForContext_ns;context=%1s;count=10;index=%1s;lang=en-US;namespace=yahoo_content;oauthConsumerKey=frontpage.oauth.canvassKey;oauthConsumerSecret=frontpage.oauth.canvassSecret;rankingProfile=canvassHalfLifeDecayProfile;region=US;sortBy=popular;type=null;userActivity=true'
    urlReply = 'https://www.yahoo.com/news/_td/api/resource/canvass.getReplies_ns;context=%1s;count=10;index=%1s;lang=en-US;messageId=%1s;namespace=yahoo_content;oauthConsumerKey=frontpage.oauth.canvassKey;oauthConsumerSecret=frontpage.oauth.canvassSecret;region=US;sortBy=createdAt;tags='
    urlUser = 'https://www.yahoo.com/news/_td/api/resource/canvass.getUserMessageHistory;count=10;index=%1s;lang=en-US;oauthConsumerKey=frontpage.oauth.canvassKey;oauthConsumerSecret=frontpage.oauth.canvassSecret;region=US;sortBy=createdAt;userId=%1s'
    
    现在,我在URL中插入了两个
    %1s
    ,以将所需变量插入URL,如文章id、索引或用户id。与以前一样,需要几个参数:

    params = {'bkt': ["news-d-202","newsdmcntr"],
        'device': 'desktop',
        'feature': 'cacheContentCanvas,videoDocking,newContentAttribution,livecoverage,featurebar,deferModalCluster,specRetry,newLayout,sidepic,canvassOffnet,ntkFilmstrip,autoNotif,CanvassTags',
        'intl': 'us',
        'lang': 'en-US',
        'partner': 'none',
        'prid': '5t11qvhclanab',
        'region': 'US',
        'site': 'fp',
        'tz': 'America/PICKACITY',  <-- insert a city
        'ver': '2.0.7765',
        'returnMeta': 'true'}
    
    从那里,您可以从评论中提取任何您想要的内容。现在,
    coms
    中只有10条注释(如果您查看URL,您将看到
    count=10
    ——不幸的是,最大值似乎是30)。要获得下一组10,请将
    coms[-1]['index']
    值插入所需的URL,然后获取下一组10。然而,我遇到的问题是,在雅虎出击之前,你只能获得大约1000条评论。例如,如果你访问,你会看到评论1000-1009(找到一个“索引”值,你会得到类似
    v=1:s=popular的东西)
    
    params = {'bkt': ["news-d-202","newsdmcntr"],
        'device': 'desktop',
        'feature': 'cacheContentCanvas,videoDocking,newContentAttribution,livecoverage,featurebar,deferModalCluster,specRetry,newLayout,sidepic,canvassOffnet,ntkFilmstrip,autoNotif,CanvassTags',
        'intl': 'us',
        'lang': 'en-US',
        'partner': 'none',
        'prid': '5t11qvhclanab',
        'region': 'US',
        'site': 'fp',
        'tz': 'America/PICKACITY',  <-- insert a city
        'ver': '2.0.7765',
        'returnMeta': 'true'}
    
    response = requests.get(u, params=params) #u is a url from above
    coms = response.json()['data']['canvassMessages'] #drop the ['canvassMessages'] if you want to get replies to a thread