私は2つのソリューションを思いついた。 1)大規模なサイトが多すぎる場合は、別のプロセスでスパイダーを実行します。 2)Twisted で遅延とコールバックを使用してください(逃げないでください、恐ろしくないでしょう)。私は最初のものが単にグーグルであることができるので、第2の方法を使用する方法を議論するでしょう。
yield request
を実行するすべての関数は、結果が利用可能になるまで「ブロック」します。したがって、parse_some_page()
関数は、応答レスポンスオブジェクトを生成し、応答が返されるまで次の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()
を介して)チェーンされていることです。今scrapy.Request
ためcallback
パラメータを見てみましょう:
yield scrapy.Request(
url=url,
callback=deferred.callback)
このスニペットが何をするかは、scrapy.Response
はリクエストから利用可能になった直後にコールバックチェーンを開始しています。 Twistedでは、が値とともに実行された後にのみ、コールバックチェーンを実行し始めます。
応答が提供された後、parse_some_page()
関数は、Response
を引数として実行されます。ここで必要なものを抽出し、次のコールバックに渡します(つまりwrite_to_disk()
私の例)。必要に応じて、ループ内のDeferred
にさらにコールバックを追加できます。
この回答と最初のやりとりの違いは、最初にすべての応答を待ち、次にコールバックを実行するためにyield
を使用したことです。私の方法では各リクエストのコールバックとしてDeferred.callback()
を使用しているので、各応答は即座に処理されます。
これは(うまくいけば)役立ちます。
参照
PS
私が解析するには大きすぎるのサイトを見つけることができなかったので、これは実際にあなたのために働く場合、私は見当もつかない。また、私はScrapy:Dで新しいブランドスパンキンですが、私は自分のベルトの下に何年ものTwistedを持っています。
私は間違っているかもしれませんが、あなたが '' parse_some_page() ''で '' result''を返すので、このシナリオが発生すると思います。利回りを取り除くとどうなりますか? –
@ notorious.no私が 'yield'を省略すると、新しいリクエストをどうすればいいのか分かりません。 – Ci3