Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/grails/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 难以格式化零碎的输出_Python_Web Crawler_Scrapy - Fatal编程技术网

Python 难以格式化零碎的输出

Python 难以格式化零碎的输出,python,web-crawler,scrapy,Python,Web Crawler,Scrapy,我是一个Python新手,正在开发一个Scrapy spider,它旨在检索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-chica

我是一个Python新手,正在开发一个Scrapy spider,它旨在检索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']
[...]

我曾尝试将其导出为项目,但最终得到了相同的结果。我相信我可能需要某种系列化或其他东西来促进我想要的东西,但我的技术已经到了极限。任何帮助都将不胜感激

脚本看起来不错,除了一件事:
reviews
指向一个
,它是页面上所有评论的包装,而不是每个评论的包装。因此,当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 without actions”]')
,您就会明白我的意思(只需查看Yelp页面上的16支蜡烛,我就可以看到每个单独的评论都被包装在一个div中,其中包含class
review review,不包含任何操作
)。更改后,脚本中的
评论将变成一个列表,每行包含一个评论,而不是一行中的所有评论。for
循环现在有一组单独的评论要迭代,这样当它查找
//li[@class=“user name”]/a/text()时
,例如,在每次迭代中,它只会找到一个匹配项(而不是页面中的所有匹配项)


编辑:tl;dr:我认为这不是代码的问题,而是您在Yelp的评论页面中指向代码的位置的问题。

作为一个简短的额外说明,因为您提到了您是
Python
ScraPy
的新手,如果您想将结果导出到CSV文件,您可以做一些额外的更改:在for循环中,在顶部添加一行,如
parsedReview=YelpItem()
(如果这是items.py中的Item类)。然后,如果在items.py中定义了“reviewer”列,则可以将此处的reviewers行更改为
parsedReview[“reviewer”]=review.xpath(…
。在脚本结束时,您可以
返回parsedReview
。然后使用
scrapy craw yelpsider-o test.csv-t csv'
运行爬行器。我没有时间编辑上面的注释。它应该是“在
parse
函数结束时”而不是“在脚本结束时”。对此表示抱歉。