item
オブジェクトがあり、単一のアイテムにデータを保存するために多くのページに沿ってそれを渡す必要があります
私のアイテムが好きです
class DmozItem(Item):
title = Field()
description1 = Field()
description2 = Field()
description3 = Field()
現在、これら3つの説明は3つの別々のページにあります。私は次のような苦労をしたい
これはparseDescription1
def page_parser(self, response):
sites = hxs.select('//div[@class="row"]')
items = []
request = Request("http://www.example.com/lin1.cpp", callback =self.parseDescription1)
request.meta['item'] = item
return request
def parseDescription1(self,response):
item = response.meta['item']
item['desc1'] = "test"
return item
しかし、私は次のようなものが欲しい
def page_parser(self, response):
sites = hxs.select('//div[@class="row"]')
items = []
request = Request("http://www.example.com/lin1.cpp", callback =self.parseDescription1)
request.meta['item'] = item
request = Request("http://www.example.com/lin1.cpp", callback =self.parseDescription2)
request.meta['item'] = item
request = Request("http://www.example.com/lin1.cpp", callback =self.parseDescription2)
request.meta['item'] = item
return request
def parseDescription1(self,response):
item = response.meta['item']
item['desc1'] = "test"
return item
def parseDescription2(self,response):
item = response.meta['item']
item['desc2'] = "test2"
return item
def parseDescription3(self,response):
item = response.meta['item']
item['desc3'] = "test3"
return item
問題ない。コードの正しいバージョンは次のとおりです。
def page_parser(self, response):
sites = hxs.select('//div[@class="row"]')
items = []
request = Request("http://www.example.com/lin1.cpp", callback=self.parseDescription1)
request.meta['item'] = item
yield request
request = Request("http://www.example.com/lin1.cpp", callback=self.parseDescription2, meta={'item': item})
yield request
yield Request("http://www.example.com/lin1.cpp", callback=self.parseDescription3, meta={'item': item})
def parseDescription1(self,response):
item = response.meta['item']
item['desc1'] = "test"
return item
def parseDescription2(self,response):
item = response.meta['item']
item['desc2'] = "test2"
return item
def parseDescription3(self,response):
item = response.meta['item']
item['desc3'] = "test3"
return item
リクエスト/コールバックの順序を保証し、1つのアイテムのみが最終的に返されるようにするには、次のようなフォームを使用してリクエストをチェーンする必要があります。
def page_parser(self, response):
sites = hxs.select('//div[@class="row"]')
items = []
request = Request("http://www.example.com/lin1.cpp", callback=self.parseDescription1)
request.meta['item'] = Item()
return [request]
def parseDescription1(self,response):
item = response.meta['item']
item['desc1'] = "test"
return [Request("http://www.example.com/lin2.cpp", callback=self.parseDescription2, meta={'item': item})]
def parseDescription2(self,response):
item = response.meta['item']
item['desc2'] = "test2"
return [Request("http://www.example.com/lin3.cpp", callback=self.parseDescription3, meta={'item': item})]
def parseDescription3(self,response):
item = response.meta['item']
item['desc3'] = "test3"
return [item]
各コールバック関数はアイテムまたはリクエストのイテラブルを返し、リクエストはスケジュールされ、アイテムはアイテムパイプラインを通じて実行されます。
各コールバックからアイテムを返すと、パイプラインでさまざまな完全な状態の4つのアイテムになりますが、次のリクエストを返すと、リクエストの順序を保証でき、正確になります実行終了時に1つのアイテム。
受け入れられた回答は、合計3つのアイテムを返します[desc(i)をi = 1,2,3に設定]。
単一のアイテムを返す場合、Dave McLainのアイテムは機能しますが、アイテムを返すには、エラーなしで正常に実行され、parseDescription1
、parseDescription2
、およびparseDescription3
が必要です。
私のユースケースでは、サブリクエストの一部がHTTP 403/404エラーをランダムに返す可能性があるため、一部をスクレイプできたとしても、一部のアイテムを失いました。
したがって、現在、次の回避策を採用しています:request.meta
dictでアイテムを渡すだけでなく、知っているcall stackを渡します次に呼び出す要求。 (スタックが空でない限り)スタック上の次のアイテムを呼び出し、スタックが空の場合はアイテムを返します。
errback
リクエストパラメータは、エラー時にディスパッチャメソッドに戻り、次のスタックアイテムを続行するために使用されます。
def callnext(self, response):
''' Call next target for the item loader, or yields it if completed. '''
# Get the meta object from the request, as the response
# does not contain it.
meta = response.request.meta
# Items remaining in the stack? Execute them
if len(meta['callstack']) > 0:
target = meta['callstack'].pop(0)
yield Request(target['url'], meta=meta, callback=target['callback'], errback=self.callnext)
else:
yield meta['loader'].load_item()
def parseDescription1(self, response):
# Recover item(loader)
l = response.meta['loader']
# Use just as before
l.add_css(...)
# Build the call stack
callstack = [
{'url': "http://www.example.com/lin2.cpp",
'callback': self.parseDescription2 },
{'url': "http://www.example.com/lin3.cpp",
'callback': self.parseDescription3 }
]
return self.callnext(response)
def parseDescription2(self, response):
# Recover item(loader)
l = response.meta['loader']
# Use just as before
l.add_css(...)
return self.callnext(response)
def parseDescription3(self, response):
# ...
return self.callnext(response)
このソリューションは依然として同期的であり、コールバック内に例外があると失敗します。
詳細については、 そのソリューションについて書いたブログ投稿を確認してください 。