0

誰かがこれを手伝ってくれませんか。私はこの情報を 2 日間探していましたが、うまくいきませんでした。

別のアイテムのリストとして 1 つのフィールドを持つアイテムがあります。スパイダーは正常に動作しますが、出力ファイルにはこの項目のすべての行が含まれています。

たとえば、json を次のように出力する必要があります。

{"id": "AAAA", "details": [
{"date" : "2013-01-10", type="A"},
{"date" : "2013-02-10", type="B"},
{"date" : "2013-03-10", type="C"},
{"date" : "2013-04-10"}, type="D"]}

しかし、私は得る:

{"id": "AAAA", "details": [
{"date" : "2013-01-10", type="A"}]}

{"id": "AAAA", "details": [
{"date" : "2013-01-10", type="A"},
{"date" : "2013-02-10", type="B"}]}

{"id": "AAAA", "details": [
{"date" : "2013-01-10", type="A"},
{"date" : "2013-02-10", type="B"},
{"date" : "2013-03-10", type="C"}
]}

{"id": "AAAA", "details": [
{"date" : "2013-01-10", type="A"},
{"date" : "2013-02-10", type="B"},
{"date" : "2013-03-10", type="C"},
{"date" : "2013-04-10"}, type="D"]}

関数を使用して親アイテムを更新します。

def rePackIt(parent, item):
    if 'details' in parent:
        items = parent.get('details')
    else:
        items = []
    items.append(dict(item))
    parent['details'] = items

return parent

解析関数では、次のことを行います。

parent = ParentItem()
parent['id'] = self.param   # actually I parse a text file with many IDs
parent['details'] = []

yield FormRequest.from_response(response,
                                    formname='...',
                                    formdata={'...':'...', '...': parent['id'], 
                                              '...':''},
                                    meta = {'parent': parent, 'dont_merge_cookies': True},
                                    callback=self.parse1)


def parse1(self, response):
    parent = response.meta['parent']
    sel = HtmlXPathSelector(response)
    records = sel.select('//ul[@class="...."]')
    for record in records:
        item = DetailItem()
        item['type'] = record.select('child...')
        doc_link = record.select('child.../a/@href').extract()
        yield Request(doc_link,
                              callback=self.parse2,
                              method='GET',
                              headers={...},
                              meta={'dont_merge_cookies': True, 'cookiejar': cookieJar, 'item'  : item, 'parent' : parent}
                          )
  def parse2(self, response):
      item = response.meta['item']
      parent = response.meta['parent']
      sel = HtmlXPathSelector(response)
      # some other parsing code
      item['date'] = cell.select('span[1]/text()[1]').extact()
      rePackIt(parent, item)
      return parent
4

1 に答える 1

1

破棄してjsonとして出力しようとしているページは、この構造を持っています

  • MainItem 1 {いくつかの情報}

    • 詳細項目 1

    • 詳細項目 2

  • メインアイテム2

    • 詳細項目 1

    • 詳細項目 2

破棄された詳細アイテムごとに親オブジェクトを返しています。あなたの意図は、「完了」した後、親オブジェクトを一度だけ返すことです。つまり、親にはすべての詳細なアイテム 1..n が取り込まれます。問題は、親アイテムの作成をいつ終了したかを伝えるより適切な方法がないことです。

これを処理する方法の 1 つは、パイプラインを作成することです ( http://doc.scrapy.org/en/latest/topics/item-pipeline.html )。これは複雑に聞こえるかもしれませんが、そうではありません。

基本的に、パイプラインには 3 つのステップがあります。

open_spider

フォームのグローバルオブジェクトを作成します

アイテムリスト = []

処理項目

if item is parent then
   add the item to the list 
if item is child then
   find the parentitem from the itemlist
   parentitem["detail"].add(childitem)

close_spider

json シリアライズを書き込み、目的のファイルに書き込みます。これに関する 1 つの注意点は、巨大なデータをスクラップする場合、json アイテムをストリーム書き込みできないため、このメソッドでそれらをファイルに書き込むまで、スクラップされたすべてのアイテムがメモリ内に存在することです。

これが機能するかどうか、またはより良い解決策を見つけたかどうかをお知らせください。

于 2013-11-01T12:06:04.130 に答える