2012-11-23 25 views
15

Fazla bilgi paylaşabilecek çeşitli web sitelerini taramak için Scrapy kullanıyorum.Scrapy - Bir öğenin sessizce bırakılması

Kazıdığım her sayfa için, sayfanın URL'sini, başlığını ve html kodunu mongoDB'ye depolarım. Veritabanında çoğaltmayı önlemek istiyorum, böylece benzer bir öğenin zaten depolanmış olup olmadığını kontrol etmek için bir boru hattı uyguluyorum. Böyle bir durumda, DropItem istisnasını yükseltirim.

Sorunum, bir öğeyi DropItem istisnasına göre her ne zaman düşürdüğüm, Scrapy öğenin tüm içeriğini günlüğe (stdout veya dosya) gösterecektir. Her bir alıntılanan sayfanın tüm HTML kodunu ayıklarken, bir damla durumunda, HTML kodunun tamamı günlüğe görüntülenecektir.

İçeriği olmadan bir öğeyi sessizce nasıl bırakabilirim?

Zaman ayırdığınız için teşekkür ederiz!

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 

cevap

16

Bunu yapmanın en uygun yolu projeniz için özel LogFormatter uygulamak gibi gözüküyor, ve değişim bırakılan öğelerin günlüğe kaydetme düzeyi.

Örnek:

ayarlarınız dosyasında Sonra
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, 
     } 

, gibi bir şey: Kötü şans vardı

LOG_FORMATTER = 'apps.crawler.spiders.PoliteLogFormatter' 

sadece gelecekteki boru hatları istisnalar neden "Yok," dönüyor.

+0

bu nereye gidiyor? Ara katman? Boru hatları? – Xodarap777

+2

@ Xodarap777, bence middlewares.py dosyası daha uygun. Ya da "logformatter.py" gibi yeni bir dosya oluşturabilirsiniz. Bu cevabın kodu, örümcek ile dosyaya kod koymayı teklif ediyor. ** Not **: Bu kod kullanımdan kaldırılmıştır, ancak aşağıdaki @mirosval'ın cevabı güncellenmiş çalışma sürümüne sahiptir. – kupgov

10

Tamam, sorunun yanıtını göndermeden önce cevabı buldum. Yine de cevabın aynı sorunu yaşayan herkes için değerli olabileceğini düşünüyorum.

yerine DropItem hariç nesneyi bırakma, sen sadece bir Hiçbiri değeri döndürmek zorunda:

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

bu dize 'Hiçbiri' yerine bırakılan öğeyi içeren bir uyarı seviyesi günlük girdisi içeren bir hata ayıklama seviyesi günlük girdisi verir yapmak. '--loglevel = INFO' veya üstü gibi adil bir çözümdür. İdeal olarak, scrapy.core.scraper.Scraper', '_itemproc_finished' içindeki çıkışın yapılandırmasına kolay erişime izin vermelidir. – jah

+0

@jah doğrudur. "jimmytheleaf" ın çözümü bu örnekte doğru olanıdır. –

7

Son Scrapy sürümlerinde, bu biraz değiştirildi. Ben @jimmytheleaf kodu kopyalanan ve son scrapy çalışmak için sabit:

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

Bu benim için harika çalıştı! Ben 'level' değiştirmeyi öneririm: logging.INFO, ''level': logging.DEBUG,' ve LOG_FORMATTER = '. . Settings.py dosyasında .PoliteLogFormatter'' – UriCS