2012-11-23 10 views
15

Scrapyを使用して複数のWebサイトをクロールしています。Scrapy - アイテムを静かにドロップする

私が掻き集めるページごとに、ページのURL、タイトル、およびHTMLコードをmongoDBに保存します。 私はデータベースに重複を避けたいので、類似の項目が既に格納されているかどうかを確認するためにパイプラインを実装します。このような場合、私はDropItem例外を発生させます。

raisonでアイテムをドロップするたびに、DropItemの例外が発生すると、Scrapyはアイテムの全内容をログ(stdoutまたはファイル)に表示します。 各スクレイプページのHTMLコード全体を抽出するので、ドロップすると、HTMLコード全体がログに表示されます。

コンテンツを表示せずにアイテムを静かにドロップするにはどうすればよいですか?

ありがとうございました!

class DatabaseStorage(object): 
    """ Pipeline in charge of database storage. 

    The 'whole' item (with HTML and text) will be stored in mongoDB. 
    """ 

    def __init__(self): 
     self.mongo = MongoConnector().collection 

    def process_item(self, item, spider): 
     """ Method in charge of item valdation and processing. """ 
     if item['html'] and item['title'] and item['url']: 
      # insert item in mongo if not already present 
      if self.mongo.find_one({'title': item['title']}): 
       raise DropItem('Item already in db') 
      else: 
       self.mongo.insert(dict(item)) 
       log.msg("Item %s scraped" % item['title'], 
        level=log.INFO, spider=spider) 
     else: 
      raise DropItem('Missing information on item %s' % (
       'scraped from ' + item.get('url') 
       or item.get('title'))) 
     return item 

答えて

16

これを行うための適切な方法は、あなたのプロジェクトのためのカスタムLogFormatterを実装することになりそうだ、と変更ドロップされたアイテムのロギングレベル

例:あなたの設定ファイルで次に

from scrapy import log 
from scrapy import logformatter 

class PoliteLogFormatter(logformatter.LogFormatter): 
    def dropped(self, item, exception, response, spider): 
     return { 
      'level': log.DEBUG, 
      'format': logformatter.DROPPEDFMT, 
      'exception': exception, 
      'item': item, 
     } 

、のようなもの:

LOG_FORMATTER = 'apps.crawler.spiders.PoliteLogFormatter' 

は、私はちょうど将来のパイプラインで例外を引き起こした "なし、" 返さない不運がありました。

+0

これはどこですか?ミドルウェア?パイプライン? – Xodarap777

+2

@ Xodarap777、私は 'middlewares.py'ファイルがより適切だと思います。あるいは、 'logformatter.py'のような新しいファイルを作成することもできます。この回答のコードは、スパイダーを使ってファイルにコードを入れることを示しています。 **注**:このコードは廃止されましたが、下記の@mirosvalの回答が作業バージョンを更新しました。 – kupgov

10

私は質問を投稿する前に答えを見つけました。 私はまだ答えが同じ問題を抱えている人にとって価値があると思います。

代わりDropItemの例外を除いて、オブジェクトをドロップすると、あなただけなし値を返す必要があります:

def process_item(self, item, spider): 
    """ Method in charge of item valdation and processing. """ 
    if item['html'] and item['title'] and item['url']: 
     # insert item in mongo if not already present 
     if self.mongo.find_one({'url': item['url']}): 
      return 
     else: 
      self.mongo.insert(dict(item)) 
      log.msg("Item %s scraped" % item['title'], 
       level=log.INFO, spider=spider) 
    else: 
     raise DropItem('Missing information on item %s' % (
      'scraped from ' + item.get('url') 
      or item.get('title'))) 
    return item 
+1

が、これは文字列「なし」の代わりにドロップされたアイテムを含む警告レベルのログエントリを含まないデバッグレベルのログエントリを出力行います。それは '--loglevel = INFO'またはそれ以上での公正な解決策です。理想的には、 'scrap.core.scraper.Scraper'は' _itemproc_finished'の出力の設定に簡単にアクセスできるようにするべきです。 – jah

+0

@jahが正しいです。この場合、 "jimmytheleaf"の解が正しいです。 –

7

最近のScrapyバージョンでは、これは少し変更されています。私は@jimmytheleafからコードをコピーして、それが最近Scrapyで動作するように固定さ:

import logging 
from scrapy import logformatter 


class PoliteLogFormatter(logformatter.LogFormatter): 
    def dropped(self, item, exception, response, spider): 
     return { 
      'level': logging.INFO, 
      'msg': logformatter.DROPPEDMSG, 
      'args': { 
       'exception': exception, 
       'item': item, 
      } 
     } 
+2

それは私にとって素晴らしい仕事でした!私は '' level ':logging.INFO、 '' level':logging.DEBUG、 'を変更し、' LOG_FORMATTER = 'に言及することをお勧めします。 settings.pyファイルの .PoliteLogFormatter'' – UriCS

関連する問題