使用scrapy踩的坑之如何使用scrapy实现递归爬取
因为对scrapy并不了解,所以在做使用scrapy爬取网站上的所有图片时,并不知道如何能够不断的循环爬取,在网上找到一篇文章:
Some Experiences Of Using Scrapy,文章中提到:
不断的抓取下一个链接如何实现,items如何保存?
这里需要解释一下parse()方法,parse可以返回Request列表,或者items列表,如果返回的是Request,则这个Request会放到下一次需要抓取的队列,如果返回items,则对应的items才能传到pipelines处理(或者直接保存,如果使用默认FEED exporter)。那么如果由parse()方法返回下一个链接,那么items怎么返回保存? Request对象接受一个参数callback指定这个Request返回的网页内容的解析函数(实际上start_urls对应的callback默认是parse方法),所以可以指定parse返回Request,然后指定另一个parse_item方法返回items:
def parse(self, response): # doSomething return [Request(url, callback=self.parse_item)] def parse_item(self, response): # item['key'] = value return [item]
关于解析函数的返回值,除了返回列表,其实还可以使用生成器,是等价的:
def parse(self, response): # doSomething yield Request(url, callback=self.parse_item) def parse_item(self, response): yield item
但是自己在实践的过程中发现上面提到的方法好像并不可行。第一个代码片段,因为Request 的callback 为parse_item 所以并没有新的请求提交到parse方法中,那就是没有实现所谓的递归爬取了?第二个代码片段也是如此。而且个人觉得return和yield在案例中能算是等价的吗?此处存疑,因为作者觉得例子中的parse_item方法中没有出现for循环,如果使用return,就只能执行一个整个方法就返回(return)了,跟yield并不一样。
后来又找到了有一个人在segmentfault问的问题scrapy如何迭代爬去? 第二个答案里答主给了一个爬取汽车数据的DEMO,看到他的一个方法里面有两个yield,才明白yield和return是不同的,之前被网上的一些DEMO给忽悠住了,以为yield和return差不多(都怪自己的python太菜o(╥﹏╥)o),所以先来了解一下yield:Python yield 使用浅析
弄明白了这个,下面感觉就好办了。
下面重点来了
def parse(self, response): # doSomething for item in items yield item for url in urls yield Request(url, callback=self.parse)
感觉上面才是实现递归爬取的正确道路。但是事情到这儿并没有结束,因为一开始我也不是按上面的格式来写的,而是走了个弯路(┳Д┳)
def parse_item(self, response): # doSomething for item in items yield item
def parse(self, response): # doSomething self.parse_item(response) for url in urls yield Request(url, callback=self.parse)
这里是项目的blog:使用scrapy爬取网站上的所有图片
完整的代码:https://github.com/wly2014/ImageSpider
以为这样就完了吗?♪(´ε`)
个人想,就只是把负责item操作部分的代码提取出来形成新的方法,这样不应该代码结构更清楚吗?so easy↖(^ω^)↗?
但是,却! 不! 行! ,运行起来没有任何的结果,或者说反应,难道是我的代码写错了,还是说上面的理解全是错的?为什么?
这儿找到了一篇相似的问题的文章scrapy递归抓取网页数据 作者最后好像也没有弄明白是怎么回事(●´ω`●)。
如果有大神知道原因或上面分析有错误之处,希望可以告知一下(๑^ں^๑)
神龙|纯净稳定代理IP免费测试>>>>>>>>天启|企业级代理IP免费测试>>>>>>>>IPIPGO|全球住宅代理IP免费测试