我想出了2個解決方案。 1)如果大型站點太多,請在單獨的進程中運行spider。 2)通過扭曲使用延期和回調(請不要跑掉,這不會太可怕)。我將討論如何使用第二種方法,因爲第一種方法可以簡單地用Google搜索。
執行yield request
的每個函數都會「阻塞」,直到結果可用。因此,您的parse_some_page()
函數會生成scrapy響應對象,並且在返回響應之前不會繼續下一個URL。我設法找到了一些需要一段時間才能獲取的網站(主要是外國政府網站),並希望它能模擬出您遇到的類似情況。這裏是一個快速和簡單的例子:
# spider/stackoverflow_spider.py
from twisted.internet import defer
import scrapy
class StackOverflow(scrapy.Spider):
name = 'stackoverflow'
def start_requests(self):
urls = [
'http://www.gob.cl/en/',
'http://www.thaigov.go.th/en.html',
'https://www.yahoo.com',
'https://www.stackoverflow.com',
'https://swapi.co/',
]
for index, url in enumerate(urls):
# create callback chain after a response is returned
deferred = defer.Deferred()
deferred.addCallback(self.parse_some_page)
deferred.addCallback(self.write_to_disk, url=url, filenumber=index+1)
# add callbacks and errorbacks as needed
yield scrapy.Request(
url=url,
callback=deferred.callback) # this func will start the callback chain AFTER a response is returned
def parse_some_page(self, response):
print('[1] Parsing %s' % (response.url))
return response.body # this will be passed to the next callback
def write_to_disk(self, content, url, filenumber):
print('[2] Writing %s content to disk' % (url))
filename = '%d.html' % filenumber
with open(filename, 'wb') as f:
f.write(content)
# return what you want to pass to the next callback function
# or raise an error and start Errbacks chain
我已經改變了稍微有點更容易閱讀和運行。在start_requests()
中首先要注意的是對象被創建並且回調函數在urls
循環內被鏈接(通過addCallback()
)。現在來看看callback
參數scrapy.Request
:
yield scrapy.Request(
url=url,
callback=deferred.callback)
什麼這個片段將要做的就是開始scrapy.Response
變爲可用從請求後,立即回調鏈。在Twisted中,Deferreds
只有在執行Deferred.callback(result)
後纔開始運行回調鏈。
提供響應後,parse_some_page()
函數將以Response
作爲參數運行。你要做的是從這裏提取你需要的東西,並將它傳遞給下一個回調(即我的例子中的write_to_disk()
)。如有必要,您可以在循環中向Deferred
添加更多回調。
所以這個答案和你最初做什麼之間的區別是,你使用yield
先等待所有的響應,然後執行回調。在我的方法中,使用Deferred.callback()
作爲每個請求的回調,以便每個響應都能立即處理。
希望這有助於(和/或工作)。
參考
PS
我不知道這是否會真正爲你工作,因爲我無法找到一個網站,過大解析。另外,我是Scrapy:D的全新品牌Spankin,但我的腰帶上有多年的Twisted。
我可能是錯的,但我認爲這種情況發生是因爲你在''parse_some_page()''中產生了''result''。當你擺脫收益時會發生什麼? –
@ notorious.no我不確定如果我選擇省略「yield」,該如何處理新的請求。 – Ci3