我是一名处理Scrapy蜘蛛的Python新手,旨在检索Yelp上特定企业的所有评论。到目前为止,这是我的代码,主要有效:
from scrapy.spider import Spider
from scrapy.selector import Selector
from scrapy.http import Request
import re
# List of businesses to be crawled
RESTAURANTS = ['sixteen-chicago']
# Check number of reviews and create links to compensate for pagination
def createRestaurantPageLinks(self, response):
reviewsPerPage = 40
sel = Selector(response)
totalReviews = int(sel.xpath('//div[@class="rating-info clearfix"]//span[@itemprop="reviewCount"]/text()').extract()[0].strip().split(' ')[0])
pages = [Request(url=response.url + '?start=' + str(reviewsPerPage*(n+1)), callback=self.parse) for n in range(totalReviews/reviewsPerPage)]
return pages
class YelpSpider(Spider):
name = "yelp"
allowed_domains = ["yelp.com"]
start_urls = ['http://www.yelp.com/biz/%s' % s for s in RESTAURANTS]
def parse(self, response):
requests = []
sel = Selector(response)
reviews = sel.xpath('//div[@class="review-list"]')
for review in reviews:
venueName = sel.xpath('//meta[@property="og:title"]/@content').extract()
reviewer = review.xpath('.//li[@class="user-name"]/a/text()').extract()
reviewerLoc = review.xpath('.//li[@class="user-location"]/b/text()').extract()
rating = review.xpath('.//div[@itemprop="review"]//meta[@itemprop="ratingValue"]/@content').extract()
reviewDate = review.xpath('.//meta[@itemprop="datePublished"]/@content').extract()
reviewText = review.xpath('.//p[@itemprop="description"]/text()').extract()
print venueName, reviewer, reviewerLoc, reviewDate, rating, reviewText
if response.url.find('?start=') == -1:
requests += createRestaurantPageLinks(self, response)
return requests
但是,输出并不是我的预期。我对此有所期待:
[u'venue name', u'reviewer', u'reviewer location', u'rating', u'review date', u'text of review']
[u'venue name', u'second reviewer', u'second reviewer location', u'second rating', u'second review date', u'second text of review']
[...]
但我得到的却是一行中每个变量的每个实例 - 所有评论者的名字都在一起,所有的评论日期都在一起,等等。例如:
[u'Sharon C.', u'Steven N.', u'Michelle R.', u'Raven C.', u'Shelley M.', u'Kenneth S.', u'Liz L.', u'Allison B.', u'Valerie v.', u'Joy G.', u'Aleksandra W.', u'Jennifer J.', u'Emily M.', u'Danny G.', u'atima k.', u'Anna V.', u'Matt L.', u'Jay R.', u'Miss O.', u'Kathy O.', u'Happiness L.', u'Heidi J.', u'Maria A.', u'RD E.', u'Tom M.', u'Isaac G.', u'Michael P.', u'Mark P.', u'Stephanie P.', u'Jennifer L.', u'X X.', u'Erika H.', u'Ginger D.', u'Susan E.', u'Simone J.', u'Rick G.', u'Alia K.', u'Brent C.', u'Dan B.', u'Patricia H.']
[u'Hampshire, IL', u'Chicago, IL', u'Chicago, IL', u'Chicago, IL', u'Chicago, IL', u'Indian Head Park, IL', u'Evanston, IL', u'Chicago, IL', u'Chicago, IL', u'Clearwater, FL', u'Chicago, IL', u'Worth, IL', u'Chicago, IL', u'Indianapolis, IN', u'Halifax, Canada', u'Manhattan, NY', u'Chicago, IL', u'Chicago, IL', u'Wicker Park, Chicago, IL', u'Chicago, IL', u'Chicago, IL', u'Chicago, IL', u'Evanston, IL', u'Chicago, IL', u'Chicago, IL', u'Chicago, IL', u'Chicago, IL', u'Chicago, IL', u'San Diego, CA', u'Chicago, IL', u'Chicago, IL', u'Chicago, IL', u'Chicago, IL', u'Evanston, IL', u'Chicago, IL', u'Lisle, IL', u'Chicago, IL', u'Chicago, IL', u'Winnetka, IL', u'Torrance, CA']
[...]
我已经尝试过导出作为项目,但我最终获得了同样的结果。我相信我可能需要某种系列或某种东西来促进我想要的东西,但我已经达到了我的专业知识的终点。任何帮助都会非常感激!
答案 0 :(得分:1)
该脚本看起来不错,除了一件事:reviews
指向<div>
,它是页面上所有评论的包装,而不是< em>每个单独的评论。因此,当ScraPy寻找//div[@class="review-list"]
时,它会立即返回页面上的所有评论。当它进入for
循环时,它最终只有一个项目要迭代。这一项包含了网页上的所有评论,因此,尝试获取.//li[@class="user-name"]/a/text()
,最终会同时为您提供该页面的所有评论者。
如果您将reviews = sel.xpath('//div[@class="review-list"]')
更改为reviews = sel.xpath('//div[@class="review review-with-no-actions"]')
,您就会明白我的意思(只需查看十六个蜡烛的Yelp页面,我就可以看到每个评论都包含在与班级review review-with-no-actions
)的div。通过此更改,脚本中的reviews
将成为一个列表,每行一次,而不是一行中的所有评论。 for
循环现在有一堆单独的评论要迭代,这样当它去寻找.//li[@class="user-name"]/a/text()
时,例如,在每次迭代中,它只会找到一个匹配(而不是页面上的所有匹配。)
修改: tl;博士:我认为这不是代码的问题,而是您指向Yelp审核页面的代码。< / p>