2017-04-16 8 views
0

私は掻きするサイトを持っています。メインページにはストーリーティーザーがあります。このページは開始ページの解析ページになります。私のスパイダーはそこから離れて、すべての物語(著者、評価、出版日など)に関するデータを収集します。これはスパイダーによって正しく行われます。複数のページから1つの項目(辞書)にデータを収集するPythonの治療

import scrapy 
from scrapy.spiders import Spider 
from sxtl.items import SxtlItem 
from scrapy.http.request import Request 


class SxtlSpider(Spider): 
    name = "sxtl" 

    start_urls = ['some_site'] 


    def parse(self, response): 

     list_of_stories = response.xpath('//div[@id and @class="storyBox"]') 

     item = SxtlItem() 

     for i in list_of_stories: 

      pre_rating = i.xpath('div[@class="storyDetail"]/div[@class="stor\ 
       yDetailWrapper"]/div[@class="block rating_positive"]/span/\ 
       text()').extract() 
      rating = float(("".join(pre_rating)).replace("+", "")) 

      link = "".join(i.xpath('div[@class="wrapSLT"]/div[@class="title\ 
       Story"]/a/@href').extract()) 

      if rating > 6: 
       yield Request("".join(link), meta={'item':item}, callback=\ 
                  self.parse_story) 
      else: 
       break 

    def parse_story(self, response): 

     item = response.meta['item'] 

     number_of_pages = response.xpath('//div[@class="pNavig"]/a[@href]\ 
             [last()-1]/text()').extract() 

     if number_of_pages: 
      item['number_of_pages'] = int("".join(number_of_pages)) 
     else: 
      item['number_of_pages'] = 1 

     item['date'] = "".join(response.xpath('//span[@class="date"]\ 
               /text()').extract()).strip() 
     item['author'] = "".join(response.xpath('//a[@class="author"]\ 
               /text()').extract()).strip() 
     item['text'] = response.xpath('//div[@id="storyText"]/div\ 
       [@itemprop="description"]/text() | //div[@id="storyText"]\ 
         /div[@itemprop="description"]/p/text()').extract() 
     item['list_of_links'] = response.xpath('//div[@class="pNavig"]\ 
              /a[@href]/@href').extract() 

     yield item 

したがって、データは正しく収集されますが、すべての記事の最初のページしかありません。しかし、すべてのソリはいくつかのページを持っています(そして2,3ページ、時には15ページにリンクしています)。それが問題の原因です。私はこれで降伏アイテムを置き換えます(すべての物語の第二のページを取得する)

yield Request("".join(item['list_of_links'][0]), meta={'item':item}, \ 
               callback=self.get_text) 


def get_text(self, response): 

    item = response.meta['item'] 

    item['text'].extend(response.xpath('//div[@id="storyText"]/div\ 
     [@itemprop="description"]/text() | //div[@id="storyText"]\ 
       /div[@itemprop="description"]/p/text()').extract()) 

    yield item 

をSpiderは、次の(第2回)のページを収集し、それがどんな物語の最初のページにそれらを結合します。例えば、第1話の第2ページが第4話に追加されてもよい。第5話の2ページ目が第1話に追加されます。等々。

複数のウェブページに掻き集めるデータが散在している場合、1つのアイテム(1つの辞書)にデータを収集する方法をお手伝いしてください。 (この場合 - 異なるアイテムのデータが混在しないようにする方法)

ありがとう。

+1

このリンクをチェックしてください:http://stackoverflow.com/questions/13910357/how-can-i-use-multiple-requests-and-pass-items-in-between-them-in-scrapy-python ? – Wandrille

+0

@Wandrille私はすでに解決策を見つけましたが、面白いリンクに感謝します。 –

答えて

0

。また、parse_storyのitem = response.meta ['item'] "行を削除する必要があります。そして、もちろん、 "パース" の

yield Request("".join(link), meta={'item':item}, callback=self.parse_story) 

yield Request("".join(link), callback=self.parse_story) 

なぜに変更する必要がありますか? Itemは一度だけ宣言され、そのフィールドは常に書き換えられていたからです。ドキュメントには1ページしかないのですが、まるですべてがOKで、まるで「新しい」アイテムがあるかのように見えます。しかし、ストーリーが複数のページを持っている場合、このアイテムはいくつかの混沌とし​​た方法で上書きされており、私たちは混沌とした結果を受け取ります。まもなく、新しいアイテムは、保存するアイテムオブジェクトの数だけ作成する必要があります。

"item = SxtlItem()"を適切な場所に移動した後、すべてが完全に機能します。

1

非技術的に: -

1)スクレイプストーリー第一ページ 2)それは 3を複数のページを持っているか、いない場合)を確認していない場合は、ちょうどyieldアイテム 4)それは次のページのボタンがある場合/そのリンクをスクラップし、データの辞書全体を次のコールバックメソッドに渡します。

item = SxtlItem() 

商品の宣言はparse_story関数の先頭に解析機能から移動する必要があります:多くの試みと私は解決策を見つけたドキュメントの全体の束を読んだ後

def parse_story(self, response): 

    item = response.meta['item'] 

    number_of_pages = response.xpath('//div[@class="pNavig"]/a[@href]\ 
            [last()-1]/text()').extract() 

    if number_of_pages: 
     item['number_of_pages'] = int("".join(number_of_pages)) 
    else: 
     item['number_of_pages'] = 1 

    item['date'] = "".join(response.xpath('//span[@class="date"]\ 
              /text()').extract()).strip() 
    item['author'] = "".join(response.xpath('//a[@class="author"]\ 
              /text()').extract()).strip() 
    item['text'] = response.xpath('//div[@id="storyText"]/div\ 
      [@itemprop="description"]/text() | //div[@id="storyText"]\ 
        /div[@itemprop="description"]/p/text()').extract() 
    item['list_of_links'] = response.xpath('//div[@class="pNavig"]\ 
             /a[@href]/@href').extract() 

    # if it has NEXT PAGE button 
    if nextPageURL > 0: 
     yield Request(url= nextPageURL , callback=self.get_text, meta={'item':item}) 
    else: 
     # it has no more pages, so just yield data. 
     yield item 





def get_text(self, response): 

    item = response.meta['item'] 


    # merge text here 
    item['text'] = item['text'] + response.xpath('//div[@id="storyText"]/div\ 
     [@itemprop="description"]/text() | //div[@id="storyText"]\ 
       /div[@itemprop="description"]/p/text()').extract() 


    # Now again check here if it has NEXT PAGE button call same function again. 
    if nextPageURL > 0: 
     yield Request(url= nextPageURL , callback=self.get_text, meta={'item':item}) 
    else: 
     # no more pages, now finally yield the ITEM 
     yield item 
+0

ありがとうございますが、これはまさに私がやろうとしていたものです。 1)ページを持っているかどうかチェックする2)ページがあるかどうかチェックする3)そうでない場合は、4)次のページボタン/リンクがあれば、そのリンクを掻き集め、次のコールバック方法。"それが失敗した後、私はちょうどサイトから1,2ページをかき集めました。とにかく、私は問題を解決して答えに示します。 –

+0

しかし、とにかく私はあなたの時間と注意を感謝します。ありがとう。 –