怎样动态添加Scrapy的start_urls?

经过测试 在 Scrapy 的主要抓取文件里面,添加 start_requests 方法,这是 Scrapy 提供的方法哦, 在内部直接执行 yield Request(newUrl) 就可以发起新的抓包请求。 同时需要注意的是,如果写了 复写 start_requests 方法,start_urls 的请求就失效了。来给你一个范例:

class AAA(Spider): name = "AAA" start_urls = def __init__(self): super(AAA, self).__init__() def start_requests(self): params = {\u0026#39;pageCount\u0026#39;: \u0026#39;100\u0026#39;} content = requests.get(\u0026#39;http://AAA.cc/AAA/json\u0026#39;, params) json = content.json() resultJson = json for result in resultJson: newUrl = result print("当前抓取的 Url 是:" + newUrl) yield Request(newUrl) def parse(self, response): content = response.body.decode("utf-8") print(content)

■网友
你可以看看github上有个scrapy-redis的项目GitHub - rolando/scrapy-redis: Redis-based components for Scrapy.,项目上是重写了scrapy的调度器、队列的,可以参考一下,这个项目的start_urls是动态添加的。
■网友
我今天也有这个需求,不过我还没有很好的方案。每次用start_urls列表是固定的一些目标,想动态的从redis队列里面取任务。想用信号在爬虫爬取结束的时候再读取一批数据,使用常用的def start_requests(self):方式这个start request只运行一次,所以还没找到从信号捕获的方法里面再调用start request的方法。但是可以调用爬虫里面的其他自定义方法。有个极其麻烦的替代方案,可行但是感觉有点复杂,如下:在extensions里定义def spider_idle(self, spider):即对scrapy信号spider_idle的捕获后的方法,如果在此处加上读取一批新的urls的方法,再调用Request方法勉强可用,但是感觉搞的很复杂了,同样的一套拼url的代码+拼参数字典的代码+yield scrapy.Request还有参数meta的代码得写两遍,还不能抽象出来一个函数,因为这些必须即写在start request里和你信号函数能调用的函数里。写的有点乱……或者直接看这里投机取巧的替代方法二:每次爬虫运行都在start request里取一批任务,然后配置上crontab定时任务,不停的做完就重启,重启就读一批新的url任务,是不是也能实现动态添加的目的
■网友
scrapy 默认采用内存队列难以直接修改;较通用的方案是hack代码,修改调度器,去重,队列持久化。看完源代码后最多一天就完成了。(已实现mongodb queue,单进程应该在200行左右,分布式的话利用frontera框架定制,大概500行吧)如果懒得看源码,简单实现就写一个 spidermiddleware,捕获spider output,定时从数据库读取url,生成新的Request,yield返回就行了,也就20行。
■网友
【怎样动态添加Scrapy的start_urls?】 在爬虫 发出 idel 信号的时候 在push 新url 到redis里 前提是 你要安装 redis-scrapy

■网友
start_urls只能添加一次,要继续添加后续需要爬取的url,使用yield Request(url)
■网友
不再调用start_urls。可以通过调用爬虫实例将url包装成request,然后加入调度队列:someone_spider.crawler.engine.schedule(some_request, someone_spider)


    推荐阅读