【问题标题】:Scrapy not giving individual results of all the reviews of a phone?Scrapy 没有给出手机所有评论的个别结果?
【发布时间】:2015-06-12 06:29:38
【问题描述】:

这段代码给了我结果,但输出不如预期。我的 xpath 有什么问题?如何将规则迭代 +10。这两个我总是有问题。

    import scrapy
from scrapy.contrib.spiders import CrawlSpider, Rule
from scrapy.selector import Selector
from scrapy.contrib.linkextractors.sgml import SgmlLinkExtractor
from urlparse import urljoin


class CompItem(scrapy.Item):
    title = scrapy.Field()
    link = scrapy.Field()
    data = scrapy.Field()
    name_reviewer = scrapy.Field()
    date = scrapy.Field()
    model_name = scrapy.Field()
    rating = scrapy.Field()
    review = scrapy.Field()



class criticspider(CrawlSpider):
    name = "flip_review"
    allowed_domains = ["flipkart.com"]

    start_urls = ['http://www.flipkart.com/samsung-galaxy-s5/product-reviews/ITME5Z9GKXGMFSF6?pid=MOBDUUDTADHVQZXG&type=all']
    rules = (
        Rule(
            SgmlLinkExtractor(allow=('.*\&start=.*',)),
            callback="parse_start_url",
            follow=True),
    )

    def parse_start_url(self, response):
        sites = response.css('div.review-list div[review-id]')
        items = []
        model_name = response.xpath('//h1[@class="title"]/text()').re(r'Reviews of (.*?)$')
        for site in sites:
            item = CompItem()
            item['model_name'] = model_name
            item['name_reviewer'] = ''.join(site.xpath('.//div[contains(@class, "date")]/preceding-sibling::*[1]//text()').extract())
            item['date'] = site.xpath('.//div[contains(@class, "date")]/text()').extract()
            item['title'] = site.xpath('.//div[contains(@class,"line fk-font-normal bmargin5 dark-gray")]/strong/text()').extract()
            item['review'] = site.xpath('.//span[contains(@class,"review-text")]/text()').extract()
            yield item

我的输出是:

 {'date': [u'\n 31 Mar 2015 ', u'\n 23 Mar 2015 '],
  'model_name': [u'\n Reviews of A & K 333 '],
  'name_reviewer': [u'\n pradeep kumar', u'\n vikas agrawal']}

我希望我的输出是:

{model_name :xyz
name_reviewer :abc
date:38383
}
{model_name :xyz
name_reviewer :hfhd
date:9283
}

我认为问题出在我的 XPath 上。

【问题讨论】:

    标签: python xpath web-scraping scrapy scrapy-spider


    【解决方案1】:

    首先,您的 XPath 表达式通常非常脆弱

    您的方法的主要问题是site 不包含评论部分,但它应该包含。换句话说,您不是在迭代页面上的评论块。

    此外,模型名称应该在循环之外提取,因为对于页面上的每条评论都是相同的。我还会使用.re() 从标题中提取型号名称,例如SAMSUNG GALAXY S5 来自REVIEWS OF SAMSUNG GALAXY S5

    这里是完整的工作代码,并应用了修复:

    def parse_start_url(self, response):
        sites = response.css('div.review-list div[review-id]')
    
        model_name = response.xpath('//h1[@class="title"]/text()').re(r'Reviews of (.*?)$')[0].strip()
        for site in sites:
            item = CompItem()
            item['model_name'] = model_name
            item['name_reviewer'] = ''.join(site.xpath('.//div[contains(@class, "date")]/preceding-sibling::*[1]//text()').extract()).strip()
            item['date'] = site.xpath('.//div[contains(@class, "date")]/text()').extract()[0].strip()
            yield item
    

    XPath 表达式也变得更简单。举例来说,评论部分由 CSS 选择器 div.review-list div[review-id] 标识,该选择器将匹配包含 review-id 属性的所有 div 元素在 div 下具有 review-list 类的任何位置。

    另外,请注意name_reviewer 是如何提取的 - 因为有不同的用户,其中一些表示为个人资料链接,有些未注册并且位于 spanreview-username 类中 - 我已经采取了不同的方法:定位审查日期并获取前一个兄弟的文本。


    我想指出,linefk-font-smallfk-font-11 等类名称是面向布局的类,一般来说,依赖于 XPath 表达式和 CSS 选择器不是一个好的选择.请注意,哪些类用于定位答案中的元素:review-listtitledate - 它们更面向数据,是定位器的更好选择。

    【讨论】:

    • 我总是觉得 xpath 的东西很难每次都怎么处理?
    • 嘿@alecxe 有一个问题,我可以看到在shell 上提取的数据,但是当我在csv 文件中打印输出时,为什么会出现空白?
    • @JohnDene 我对代码添加了更多改进。现在,当我以 scrapy runspider spider1.py -t csv -o output.csv 运行蜘蛛时,我将在 output.csv 中获取提取的数据。
    【解决方案2】:

    这应该有帮助,这是您的xpath 的问题,

    In [1]: data_list = []
    
    In [2]: sites = response.xpath('//div[@class="review-list"]/div')
    
    In [3]: for site in sites:
        data = {}
        data['name_reviewer'] = site.xpath('./div/div[@class="line"]/span[@class="fk-color-title fk-font-11 review-username"]/text()|./div/div[@class="line"]/a[@class="load-user-widget fk-underline"]/text()').extract()[0].strip()
        data['date'] = site.xpath('./div/div[@class="date line fk-font-small"]/text()').extract()[0].strip()
        data['model_name'] =  response.xpath('//h1[@class="title"]/text()').extract()[0].strip()
        data_list.append(data)
    
    
    In [4]: data_list
    Out[4]: 
    [{'date': u'10 Apr 2014',
      'model_name': u'Reviews of Samsung Galaxy S5',
      'name_reviewer': u'RISHABH GROVER'},
     {'date': u'11 Apr 2014',
      'model_name': u'Reviews of Samsung Galaxy S5',
      'name_reviewer': u'Hemraj Chaudhari'},
     {'date': u'28 Apr 2014',
      'model_name': u'Reviews of Samsung Galaxy S5',
      'name_reviewer': u'RISHABH GROVER'},
     {'date': u'27 Apr 2014',
      'model_name': u'Reviews of Samsung Galaxy S5',
      'name_reviewer': u'Debadutta Patnaik'},
     {'date': u'24 May 2014',
      'model_name': u'Reviews of Samsung Galaxy S5',
      'name_reviewer': u'Joel'},
     {'date': u'11 Apr 2014',
      'model_name': u'Reviews of Samsung Galaxy S5',
      'name_reviewer': u'Saswat Nayak'},
     {'date': u'14 Apr 2014',
      'model_name': u'Reviews of Samsung Galaxy S5',
      'name_reviewer': u'Amit Thakor'},
     {'date': u'28 May 2014',
      'model_name': u'Reviews of Samsung Galaxy S5',
      'name_reviewer': u'Nishchal Sharma'},
     {'date': u'13 May 2014',
      'model_name': u'Reviews of Samsung Galaxy S5',
      'name_reviewer': u'siddiq hassan'},
     {'date': u'16 May 2014',
      'model_name': u'Reviews of Samsung Galaxy S5',
      'name_reviewer': u'Raja Shekhar'}]
    

    【讨论】:

    • Thanx jitin 但得到错误str object has no attribute extract
    • 你在哪里得到这个错误?您能否粘贴完整的错误代码或至少粘贴错误行?
    • 可能是我使用了规则,这就是它抛出此错误的原因
    猜你喜欢
    • 2020-06-30
    • 2015-03-04
    • 2013-10-14
    • 1970-01-01
    • 1970-01-01
    • 2017-04-13
    • 2020-04-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多