2016-08-03 3 views
0

Im サブサイトから詳細をスクラップし、サイトで削り取った詳細とマージします。私はstackoverflowとドキュメントを使って研究してきました。しかし、私はまだ私のコードを動作させることはできません。サブサイトから追加の詳細を抽出する機能が動作しないようです。誰かが一見することができたら、私はとても感謝しています。Scrapyサブサイトアイテムとサイトアイテムをマージする

私は他の例(stackoverflowのは、そのための素晴らしいです!)、などscrapyドキュメントの多くと一緒にこれらの例を見て、まだ私は詳細を取得する方法を理解することができませんでし一つの関数から送信されてきた
# -*- coding: utf-8 -*- 
from scrapy.spiders import Spider 
from scrapy.selector import Selector 
from scrapeInfo.items import infoItem 
import pyodbc 


class scrapeInfo(Spider): 
    name = "info" 
    allowed_domains = ["http://www.nevermind.com"] 
    start_urls = [] 

    def start_requests(self): 

     #Get infoID and Type from database 
     self.conn = pyodbc.connect('DRIVER={SQL Server};SERVER=server;DATABASE=dbname;UID=user;PWD=password') 
     self.cursor = self.conn.cursor() 
     self.cursor.execute("SELECT InfoID, category FROM dbo.StageItem") 

     rows = self.cursor.fetchall() 

     for row in rows: 
      url = 'http://www.nevermind.com/info/' 
      InfoID = row[0] 
      category = row[1] 
      yield self.make_requests_from_url(url+InfoID, InfoID, category, self.parse) 

    def make_requests_from_url(self, url, InfoID, category, callback): 
     request = Request(url, callback) 
     request.meta['InfoID'] = InfoID 
     request.meta['category'] = category 
     return request 

    def parse(self, response): 
     hxs = Selector(response) 
     infodata = hxs.xpath('div[2]/div[2]') # input item path 

     itemPool = [] 

     InfoID = response.meta['InfoID'] 
     category = response.meta['category'] 

     for info in infodata: 
      item = infoItem() 
      item_cur, item_hist = InfoItemSubSite() 

      # Stem Details 
      item['id'] = InfoID 
      item['field'] = info.xpath('tr[1]/td[2]/p/b/text()').extract() 
      item['field2'] = info.xpath('tr[2]/td[2]/p/b/text()').extract() 
      item['field3'] = info.xpath('tr[3]/td[2]/p/b/text()').extract() 
      item_cur['field4'] = info.xpath('tr[4]/td[2]/p/b/text()').extract() 
      item_cur['field5'] = info.xpath('tr[5]/td[2]/p/b/text()').extract() 
      item_cur['field6'] = info.xpath('tr[6]/td[2]/p/b/@href').extract() 

      # Extract additional information about item_cur from refering site 
      # This part does not work 
      if item_cur['field6'] = info.xpath('tr[6]/td[2]/p/b/@href').extract(): 
       url = 'http://www.nevermind.com/info/sub/' + item_cur['field6'] = info.xpath('tr[6]/td[2]/p/b/@href').extract()[0] 
       request = Request(url, housingtype, self.parse_item_sub) 
       request.meta['category'] = category 
       yield self.parse_item_sub(url, category) 
      item_his['field5'] = info.xpath('tr[5]/td[2]/p/b/text()').extract() 
      item_his['field6'] = info.xpath('tr[6]/td[2]/p/b/text()').extract() 
      item_his['field7'] = info.xpath('tr[7]/td[2]/p/b/@href').extract()  

      item['subsite_dic'] = [dict(item_cur), dict(item_his)] 

      itemPool.append(item) 
      yield item 
     pass 

     # Function to extract additional info from the subsite, and return it to the original item. 
     def parse_item_sub(self, response, category): 
      hxs = Selector(response) 
      subsite = hxs.xpath('div/div[2]') # input base path 

      category = response.meta['category'] 

      for i in subsite:   
       item = InfoItemSubSite()  
       if (category == 'first'): 
        item['subsite_field1'] = i.xpath('/td[2]/span/@title').extract()    
        item['subsite_field2'] = i.xpath('/tr[4]/td[2]/text()').extract() 
        item['subsite_field3'] = i.xpath('/div[5]/a[1]/@href').extract() 
       else: 
        item['subsite_field1'] = i.xpath('/tr[10]/td[3]/span/@title').extract()    
        item['subsite_field2'] = i.xpath('/tr[4]/td[1]/text()').extract() 
        item['subsite_field3'] = i.xpath('/div[7]/a[1]/@href').extract() 
       return item 
      pass 

元の関数のスクラップされたアイテムとマージされます。リクエスト連鎖と呼ばれているあなたがここに探している

how do i merge results from target page to current page in scrapy? How can i use multiple requests and pass items in between them in scrapy python

答えて

2

。あなたの問題は、いくつかのリクエストから1つのアイテムを生成することです。これに対する解決策は、依頼metaの属性でアイテムを運んでいる間にリクエストをチェーンすることです。
例:

def parse(self, response): 
    item = MyItem() 
    item['name'] = response.xpath("//div[@id='name']/text()").extract() 
    more_page = # some page that offers more details 
    # go to more page and take your item with you. 
    yield Request(more_page, 
        self.parse_more, 
        meta={'item':item}) 


def parse_more(self, response): 
    # get your item from the meta 
    item = response.meta['item'] 
    # fill it in with more data and yield! 
    item['last_name'] = response.xpath("//div[@id='lastname']/text()").extract() 
    yield item 
+0

ありがとう!だから私の場合、最初のリクエストで約109のフィールドがあり、これらはすべてmeta = {'item':item}に格納されています。このように異なるクラスを送信するにはどうすればいいですか? – Philip

+0

@PhilipHoyos要求メタでオブジェクトや参照を持ち運ぶことはできますが、複雑なオブジェクト型やクラスによってメモリリークなどの問題が発生する可能性があるため、可能であれば基本的なPython型を使用したいと考えています(scrapy.Itemはかなりですちょうどpython dict btwなので、それは完全に安全です) – Granitosaurus

+0

@Granitosaurus今まで見たことのないrequest.metaのポイント説明と、最も簡単で、シンプルで、1 +いいえ、ゴブリンジクク、ちょうど「ここには、ここにそれがあります、あなたのためにそれを働かせる方法はあります。ブラボー! –