2012-11-23 21 views
15

मैं कई वेबसाइटों को क्रॉल करने के लिए स्केपर का उपयोग कर रहा हूं, जो अनावश्यक जानकारी साझा कर सकता है।स्क्रैप - चुपचाप एक आइटम

प्रत्येक पृष्ठ के लिए मैं स्क्रैप करता हूं, मैं पृष्ठ का यूआरएल, इसका शीर्षक और इसका HTML कोड, mongoDB में संग्रहीत करता हूं। मैं डेटाबेस में डुप्लिकेशन से बचना चाहता हूं, इस प्रकार, मैं यह जांचने के लिए एक पाइपलाइन लागू करता हूं कि कोई भी आइटम पहले से संग्रहीत है या नहीं। ऐसे मामले में, मैं DropItem अपवाद बढ़ाता हूं।

मेरी समस्या यह है कि जब भी मैं DropItem अपवाद को एक आइटम छोड़ देता हूं, तो स्केपर आइटम की संपूर्ण सामग्री लॉग (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

यह कहां जाता है? Middlewares? पाइपलाइन? – 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' या ऊपर पर एक उचित समाधान है। आदर्श रूप से, 'scrapy.core.scraper.Scraper' को '_itemproc_finished' में आउटपुट की कॉन्फ़िगरेशन तक आसान पहुंच की अनुमति देनी चाहिए। – jah

+0

@jah सही है। इस उदाहरण में "jimmytheleaf" का समाधान सही है। –

7

हाल के स्केच संस्करणों में, यह थोड़ा सा बदल दिया गया है। मैं @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

यह मेरे लिए बहुत अच्छा काम किया! मैं 'स्तर' को बदलने का सुझाव दूंगा: लॉगिंग .INFO, 'to' 'स्तर': logging.DEBUG, 'और 'LOG_FORMATTER =' का उल्लेख करना। settings.py फ़ाइल में .PoliteLogFormatter'' – UriCS

संबंधित मुद्दे