2017-05-22 3 views
0

私はAPIの情報を取得する次のようなSpiderを持っていますが、これ以外にもbase64形式の製品イメージをダウンロードしたいのですが、私は別の方法で、例えば、スレッドを使用してそれを行うのですか?Scrapy:別のスレッドでbase64イメージをダウンロードする

class ExampleMobilePhoneSpider(Spider): 
    name = "example" 
    allowed_domains = ["www.example.com", "example.com"] 
    start_urls = (
     'https://search.example.com/api/search/?category=c11&pageno=0', 
    ) 
custom_settings = { 
    "ITEM_PIPELINES": { 
     'crawler_bot.pipelines.ExampleElectronicDevicePipeline': 100, 
    } 
} 

def parse_item(self, response): 
    js = json.loads(response.body.decode('utf-8')) 
    hits = js['hits']['hits'] 
    for counter, hit in enumerate(hits): 
     l = ItemLoader(item=ProductDetail(), response=response) 
     m = hits[counter]['_source'] 

     # print(json.dumps(m, indent=4, sort_keys=True)) 
     l.add_value('enTitle', m['EnTitle']) 
     l.add_value('faTitle', m['FaTitle']) 
     l.add_value('minPrice', {"value": m['MinPrice'], "updateDate": datetime.datetime.now()}) 
     l.add_value('price', {"value": m['MinPriceList'], "updateDate": datetime.datetime.now()}) 
     l.add_value('maxPrice', {"value": m['MaxPrice'], "updateDate": datetime.datetime.now()}) 
     l.add_value('isActive', m['IsActive']) 
     l.add_value('isEspecialOffer', m['IsSpecialOffer']) 
     l.add_value('productCategories', m['ProductCategories'].split()) 
     l.add_value('imagePath', m['ImagePath']) 
     l.add_value('hasVideo', m['HasVideo']) 
     l.add_value('productColorList', m['ProductColorList']) 
     l.add_value('localID', m['Id']) 

     l.add_value('url', response.url) 
     l.add_value('project', "example") 
     l.add_value('subject', ["electronic_device", "mobile_phone", "mobile"]) 
     l.add_value('spider', self.name) 
     l.add_value('server', socket.gethostname()) 
     l.add_value('date', datetime.datetime.now()) 
     l.add_value('collection', "electronic_device") 

     file_path = "https://file.example.com/example/" 
     l.add_value('images', image2base64.get_as_base64(file_path + m['ImagePath'])) 

     yield l.load_item() 

def parse(self, response): 
    base_url_mobile = 'https://search.example.com/api/search/?category=c11&pageno=' 
    urls = [base_url_mobile + str(n) for n in range(2)] 
    for url in urls: 
     yield Request(urljoin(response.url, url), callback=self.parse_item) 
+0

ダウンローダーパイプラインを実装してみましたか? – Kruser

+0

パイプラインではMongoDBとElasticsearchにデータを格納するだけです – altruistic

答えて

0

以下のいくつかの方法では、リクエストと応答の処理とイメージのダウンロードを行うキューとワーカースレッドがあります。

from threading import Thread 
from Queue import Queue 


class ExampleMobilePhoneSpider(Spider): 

    def __init__(self, num_workers=10, q_size=100): 
     self.in_q = Queue(q_size) 
     self.worker_threads = [Thread(
            target=self.worker, args=(self.in_q,)) 
           for _ in range(num_workers)] 
     for _thread in self.worker_threads: 
      _thread.daemon = True 
      _thread.start() 

    def worker(self): 
     while True: 
      _url = self.in_q.get() 
      Request(_url, callback=self.parse_item) 

    def parse(self, response): 
     base_url_mobile = 'https://search.example.com/api/search/?category=c11&pageno=' 
     urls = [base_url_mobile + str(n) for n in range(2)] 
     for url in urls: 
      self.in_q.add(urljoin(response.url, url)) 
+0

コードをテストしましたか?あなたのコードは、それが実行されない多くの治療要求オブジェクトを作成するためにいくつかのスレッドをスピンアップするようになります... – rrschmidt

+0

OPコードの例が完全ではなく、悪いインデントされていないので、それに基づいてコードをテストすることはできません。具体的な質問はありましたか?これまでに何を試しましたか?これを行うにはたくさんの方法があります。スレッドのターゲット機能をイメージのダウンロードにすることは簡単にできますし、解析/治療の使用を全く行わないこともできます。それはあなたが望むものによって異なります。いずれにせよ、いくつかの作業コードを表示し、そのコードに基づいて質問する必要があります。 – danny

1

あなた自身のスレッドを治療と混合することは、通常は悪い考えです。また、ScrapyはTwistedのReactor Patternの実装を並行処理に使用しており、ハードウェアが十分な大きさであれば同時に1000sの要求を処理することができます。また、settings.pyの設定も可能です。

私はあなたのsettings.pyをあなたの画像パイプラインimplmentationを見てもいないことはできないので、これは少しは推測ですが、あなたはこれら二つのことを試してみてください:

  1. は、設定CONCURRENT_REQUESTS_PER_DOMAINとCONCURRENT_REQUESTSを高めますそうでなければ、あなたのスパイダーは同時に限られた数のページとファイルしかダウンロードしません。

  2. cpu-intensiveな処理やブロックの動作を画像パイプラインで確認してください。

関連する問題