使用Scrapy解析网站,跟随下一页并写入XML

3 投票
3 回答
4698 浏览
提问于 2025-04-16 20:34

我的脚本在我把一段代码注释掉时运行得很好:return items

这是我的代码,我把链接改成了http://example.com,因为看起来其他人也是这样做的,可能是为了避免抓取数据的法律问题。

class Vfood(CrawlSpider):
        name = "example.com"
        allowed_domains = [ "example.com" ]
        start_urls = [
                "http://www.example.com/TV_Shows/Show/Episodes"
        ]

        rules = (
                Rule(SgmlLinkExtractor(allow=('example\.com', 'page='), restrict_xpaths = '//div[@class="paginator"]/
span[@id="next"]'), callback='parse'),
        )

        def parse(self, response):
                hxs = HtmlXPathSelector(response)
                items = []
                countries = hxs.select('//div[@class="index-content"]')
                tmpNextPage = hxs.select('//div[@class="paginator"]/span[@id="next"]/a/@href').extract()
                for country in countries:
                        item = FoodItem()
                        countryName = country.select('.//h3/text()').extract()
                        item['country'] = countryName
                        print "Country Name: ", countryName
                        shows = country.select('.//div[@class="content1"]')
                        for show in shows.select('.//div'):
                                showLink = (show.select('.//h4/a/@href').extract()).pop()
                                showLocation = show.select('.//h4/a/text()').extract()
                                showText = show.select('.//p/text()').extract()
                                item['showURL'] = "http://www.travelchannel.com"+str(showLink)
                                item['showcity'] = showLocation
                                item['showtext'] = showText
                                item['showtext'] = showText
                                print "\t", showLink
                                print "\t", showLocation
                                print "\t", showText
                                print "\n"
                                items.append(item)
                        **#return items**

                for NextPageLink in tmpNextPage:
                        m = re.search("Location", NextPageLink)
                        if m:
                                NextPage = NextPageLink
                                print "Next Page:  ", NextPage
                                yield Request("http://www.example.com/"+NextPage, callback = self.parse)
                        else:
                                NextPage = 'None'
SPIDER = food()

如果我把 #return items 这行取消注释,我就会遇到以下错误:

yield Request("http://www.example.com/"+NextPage, callback = self.parse)
SyntaxError: 'return' with argument inside generator

由于我保留了注释,我无法以XML格式收集数据,但通过打印出来的结果,我确实在屏幕上看到了我应该看到的所有内容。

我用来获取XML的命令是:

scrapy crawl example.com --set FEED_URI=food.xml --set FEED_FORMAT=xml

当我取消注释return items这一行时,我可以创建XML文件,但脚本就停止了,无法继续跟踪链接。

3 个回答

1

CrawlSpider 类使用了一个叫做 Parse 的方法,所以你应该给你自己写的解析方法起个不同的名字,比如叫 parse_item()。想了解更多,可以查看“爬虫规则”这个链接 http://doc.scrapy.org/topics/spiders.html#scrapy.spider.BaseSpider

3

这个链接能回答你的问题吗?:http://www.answermysearches.com/python-fixing-syntaxerror-return-with-argument-inside-generator/354/

这个错误的意思是,当你在一个函数里使用了 yield 让它变成一个生成器时,你只能用没有参数的 return。

我还建议使用像这样的项目加载器:

def parse(self, response):
    l = XPathItemLoader(item=Product(), response=response)
    l.add_xpath('name', '//div[@class="product_name"]')
    l.add_xpath('name', '//div[@class="product_title"]')
    l.add_xpath('price', '//p[@id="price"]')
    l.add_xpath('stock', '//p[@id="stock"]')
    l.add_value('last_updated', 'today') # you can also use literal values
    return l.load_item()
4

你现在是在返回一个物品的列表(可能放错地方了),然后在同一个函数里又用到了 yield 来生成请求。在 Python 里,不能这样混用 yield 和 return。

你要么把所有东西都加到一个列表里,然后在解析方法的最后返回这个列表,要么在所有地方都使用 yield。我建议把 items.append(item) 替换成 yield item,然后把所有关于物品列表的引用都去掉。

撰写回答