Scrapy を使用するかなり複雑なマルチプロセス プログラムがあります。それは約 95% の時間で完全に動作しますが、時折、DNSLookupError/TCPTimedOutError を引き起こす悪いサイトにヒットしたときに Twisted から未処理の例外が発生します。
これは問題にはなりませんが、残念ながら、これらのエラーにより、Scrapy は BaseSpider parse メソッドをスキップします。このメソッドでは、応答を処理するために Queue を設定しました。キューをスキップするため、スキップされた URL を特定する方法がありません。
すべての Scrapy リクエストがその解析メソッドで終了することを常に保証する方法はありますか? 必要なのは、これらの失敗した応答オブジェクトにアクセスしてキューに入れる方法だけです。
これが私のスパイダーコードの例です:
class SeerSpider(BaseSpider):
"""Scrapy-based html retrieval system."""
name = "SeerSpider"
def __init__(self, spider_queue, url_list):
self.queue = spider_queue
self.allowed_domains = []
self.start_urls = []
for url in url_list:
self.allowed_domains.append(str(urlparse(url).netloc))
self.start_urls.append(url)
super(SeerSpider, self).__init__()
def parse(self, response):
"""Extracts information from each website in start_urls."""
self.queue.put(response)
ご覧のとおり、非常に基本的なものです。
その後、キューは次のように処理されます。
while True:
response = spider_queue.get()
### DO STUFF HERE ###
results_queue.put(result)
その後...
while True:
try:
result = results_queue.get(True, 60)
except:
print 'HALP', sys.exc_info()
result = ['ERROR']
self.results.append(result)
counter -= 1
if counter <= 0 or self.exit == True:
for process in process_list:
process.terminate()
break
一時的な解決策としてキューのタイムアウトを追加したため、キューに存在しないアイテムを待機するときに無期限にハングすることはありません。ある種の応答オブジェクトが start_urls リストの各 URL のキューに入ることが保証できれば、すべての問題が解決します。
ありがとう