如何動態新增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任務,是不是也能實現動態新增的目的
你可以看看github上有個scrapy-redis的專案
GitHub - rolando/scrapy-redis: Redis-based components for Scrapy。
,專案上是重寫了scrapy的排程器、佇列的,可以參考一下,這個專案的start_urls是動態新增的。
scrapy 預設採用記憶體佇列難以直接修改;較通用的方案是hack程式碼,修改排程器,去重,佇列持久化。看完原始碼後最多一天就完成了。(已實現mongodb queue,單程序應該在200行左右,分散式的話利用frontera框架定製,大概500行吧)
如果懶得看原始碼,簡單實現就寫一個 spidermiddleware,捕獲spider output,定時從資料庫讀取url,生成新的Request,yield返回就行了,也就20行。
經過測試 在 Scrapy 的主要抓取檔案裡面,新增 start_requests 方法,這是 Scrapy 提供的方法哦, 在內部直接執行
yield
Request(newUrl) 就可以發起新的抓包請求。 同時需要注意的是,如果寫了 複寫 start_requests 方法,start_urls 的請求就失效了。來給你一個範例:
class AAA(Spider):
name = “AAA”
start_urls = [
“http://www。xxx。com/handbook/201710/xxx。html”,
]
def __init__(self):
super(AAA, self)。__init__()
def start_requests(self):
params = {‘pageCount’: ‘100’}
content = requests。get(‘http://AAA。cc/AAA/json’, params)
json = content。json()
resultJson = json[“result”]
for result in resultJson:
newUrl = result[“AAAUrl”]
print(“當前抓取的 Url 是:” + newUrl)
yield Request(newUrl)
def parse(self, response):
content = response。body。decode(“utf-8”)
print(content)
在爬蟲 發出 idel 訊號的時候 在push 新url 到redis裡 前提是 你要安裝 redis-scrapy
下一篇:最全PS快捷鍵