2012-12-05 17 views
33

मैं स्केपर की नौसिखिया हूं और यह आश्चर्यजनक क्रॉलर ढांचा है जिसे मैंने जाना है!स्केपर विफलता यूआरएल कैसे प्राप्त करें?

मेरी परियोजना में, मैंने 90,000 से अधिक अनुरोध भेजे, लेकिन उनमें से कुछ विफल हो गए। मैंने लॉग स्तर को INFO होने के लिए सेट किया है, और मैं बस कुछ आंकड़े देख सकता हूं लेकिन कोई विवरण नहीं।

2012-12-05 21:03:04+0800 [pd_spider] INFO: Dumping spider stats: 
{'downloader/exception_count': 1, 
'downloader/exception_type_count/twisted.internet.error.ConnectionDone': 1, 
'downloader/request_bytes': 46282582, 
'downloader/request_count': 92383, 
'downloader/request_method_count/GET': 92383, 
'downloader/response_bytes': 123766459, 
'downloader/response_count': 92382, 
'downloader/response_status_count/200': 92382, 
'finish_reason': 'finished', 
'finish_time': datetime.datetime(2012, 12, 5, 13, 3, 4, 836000), 
'item_scraped_count': 46191, 
'request_depth_max': 1, 
'scheduler/memory_enqueued': 92383, 
'start_time': datetime.datetime(2012, 12, 5, 12, 23, 25, 427000)} 

क्या अधिक जानकारी रिपोर्ट प्राप्त करने का कोई तरीका है? उदाहरण के लिए, उन असफल यूआरएल दिखाएं। धन्यवाद!

उत्तर

42

हां, यह संभव है।

मैंने अपने स्पाइडर क्लास में एक असफल_रल्स सूची जोड़ा और प्रतिक्रिया की स्थिति 404 थी (इसे अन्य त्रुटि स्थितियों को कवर करने के लिए विस्तारित करने की आवश्यकता होगी) में यूआरएल संलग्न किया गया था।

फिर मैंने एक हैंडल जोड़ा जो सूची को एक स्ट्रिंग में शामिल करता है और स्पाइडर बंद होने पर इसे आंकड़ों में जोड़ता है।

आपकी टिप्पणियों के आधार पर, ट्विस्ट त्रुटियों को ट्रैक करना संभव है।

from scrapy.spider import BaseSpider 
from scrapy.xlib.pydispatch import dispatcher 
from scrapy import signals 

class MySpider(BaseSpider): 
    handle_httpstatus_list = [404] 
    name = "myspider" 
    allowed_domains = ["example.com"] 
    start_urls = [ 
     'http://www.example.com/thisurlexists.html', 
     'http://www.example.com/thisurldoesnotexist.html', 
     'http://www.example.com/neitherdoesthisone.html' 
    ] 

    def __init__(self, category=None): 
     self.failed_urls = [] 

    def parse(self, response): 
     if response.status == 404: 
      self.crawler.stats.inc_value('failed_url_count') 
      self.failed_urls.append(response.url) 

    def handle_spider_closed(spider, reason): 
     self.crawler.stats.set_value('failed_urls', ','.join(spider.failed_urls)) 

    def process_exception(self, response, exception, spider): 
     ex_class = "%s.%s" % (exception.__class__.__module__, exception.__class__.__name__) 
     self.crawler.stats.inc_value('downloader/exception_count', spider=spider) 
     self.crawler.stats.inc_value('downloader/exception_type_count/%s' % ex_class, spider=spider) 

    dispatcher.connect(handle_spider_closed, signals.spider_closed) 

आउटपुट (डाउनलोडर/exception_count * आंकड़े केवल दिखाई देगा, यदि अपवाद वास्तव में फेंक दिया जाता है - मैं उन्हें मकड़ी को चलाने के लिए कोशिश कर रहा द्वारा नकली के बाद मैं अपने वायरलेस एडाप्टर को बंद कर दिया था):

2012-12-10 11:15:26+0000 [myspider] INFO: Dumping Scrapy stats: 
    {'downloader/exception_count': 15, 
    'downloader/exception_type_count/twisted.internet.error.DNSLookupError': 15, 
    'downloader/request_bytes': 717, 
    'downloader/request_count': 3, 
    'downloader/request_method_count/GET': 3, 
    'downloader/response_bytes': 15209, 
    'downloader/response_count': 3, 
    'downloader/response_status_count/200': 1, 
    'downloader/response_status_count/404': 2, 
    'failed_url_count': 2, 
    'failed_urls': 'http://www.example.com/thisurldoesnotexist.html, http://www.example.com/neitherdoesthisone.html' 
    'finish_reason': 'finished', 
    'finish_time': datetime.datetime(2012, 12, 10, 11, 15, 26, 874000), 
    'log_count/DEBUG': 9, 
    'log_count/ERROR': 2, 
    'log_count/INFO': 4, 
    'response_received_count': 3, 
    'scheduler/dequeued': 3, 
    'scheduler/dequeued/memory': 3, 
    'scheduler/enqueued': 3, 
    'scheduler/enqueued/memory': 3, 
    'spider_exceptions/NameError': 2, 
    'start_time': datetime.datetime(2012, 12, 10, 11, 15, 26, 560000)} 
+0

यह अब काम नहीं करता है। 'अपवाद। नाम त्रुटि: वैश्विक नाम 'स्वयं' परिभाषित नहीं किया गया है 'त्रुटि होती है। 'बेसस्पीडर' अब सिर्फ 'स्पाइडर' है http://doc.scrapy.org/en/0.24/news.html?हाइलाइट = बेसस्पीडर # आईडी 2 https://github.com/scrapy/dirbot/blob/master/dirbot/spiders/dmoz.py लेकिन मुझे अभी तक आपका कोड काम करने के लिए फिक्स नहीं मिल रहा है। – Mikeumus

15

यहाँ एक और उदाहरण संभालने के लिए और इकट्ठा करने के लिए तरीका बताया गया है 404 त्रुटियों (जाँच GitHub सहायता पृष्ठों):

from scrapy.selector import HtmlXPathSelector 
from scrapy.contrib.spiders import CrawlSpider, Rule 
from scrapy.contrib.linkextractors.sgml import SgmlLinkExtractor 
from scrapy.item import Item, Field 


class GitHubLinkItem(Item): 
    url = Field() 
    referer = Field() 
    status = Field() 


class GithubHelpSpider(CrawlSpider): 
    name = "github_help" 
    allowed_domains = ["help.github.com"] 
    start_urls = ["https://help.github.com", ] 
    handle_httpstatus_list = [404] 
    rules = (Rule(SgmlLinkExtractor(), callback='parse_item', follow=True),) 

    def parse_item(self, response): 
     if response.status == 404: 
      item = GitHubLinkItem() 
      item['url'] = response.url 
      item['referer'] = response.request.headers.get('Referer') 
      item['status'] = response.status 

      return item 

बस -o output.json साथ scrapy runspider चलाने के लिए और देखने के output.json फ़ाइल में आइटम की सूची।

10

@ टालावलिन और @alecxe के उत्तरों ने मुझे एक बड़ा सौदा करने में मदद की, लेकिन वे डाउनलोडर घटनाओं को कैप्चर नहीं करते हैं जो प्रतिक्रिया ऑब्जेक्ट उत्पन्न नहीं करते हैं (उदाहरण के लिए, twisted.internet.error.TimeoutError और twisted.web.http.PotentialDataLoss)। ये त्रुटियां रन के अंत में आंकड़े डंप में दिखाई देती हैं, लेकिन बिना किसी मेटा जानकारी के।

जैसा कि मैंने here पता चला, त्रुटियों, Stats.py मिडलवेयर द्वारा पता लगाया जाता है DownloaderStats वर्ग 'process_exception विधि में कब्जा, और विशेष रूप ex_class चर, जो प्रत्येक त्रुटि टाइप के रूप में आवश्यक वृद्धि कर देता है, और उसके बाद में कम से मायने रखता है उदासीनता रन का अंत

, इसी अनुरोध वस्तु से जानकारी के साथ ऐसी त्रुटियों से मेल करने के लिए (request.meta के माध्यम से) प्रत्येक अनुरोध करने के लिए मेटा जानकारी जोड़ सकते हैं, तो यह Stats.py की process_exception विधि में खींच:

self.stats.set_value('downloader/my_errs/%s' % request.meta, ex_class) 

उत्पन्न होगा कि इस तरह की प्रत्येक त्रुटि के लिए एक अद्वितीय स्ट्रिंग।बदल Stats.pyMystats.py के रूप में सहेज सकते हैं, मिडलवेयर में जोड़ने (दाएं पूर्वता के साथ), और अक्षम नियमित Stats.py: रन के अंत में

DOWNLOADER_MIDDLEWARES = { 
    'myproject.mystats.MyDownloaderStats': 850, 
    'scrapy.downloadermiddleware.stats.DownloaderStats': None, 
    } 

निर्गम (इस तरह दिखता है यहाँ मेटा जानकारी जहां का उपयोग कर यूआरएल/अनुरोध पूर्णांक आधारित करने के लिए ग्रुप/memberID के मेटा str, '0/14') की तरह मैप की जाती हैं: गैर डाउनलोडर आधारित त्रुटियों के साथ

{'downloader/exception_count': 3, 
'downloader/exception_type_count/twisted.web.http.PotentialDataLoss': 3, 
'downloader/my_errs/0/1': 'twisted.web.http.PotentialDataLoss', 
'downloader/my_errs/0/38': 'twisted.web.http.PotentialDataLoss', 
'downloader/my_errs/0/86': 'twisted.web.http.PotentialDataLoss', 
'downloader/request_bytes': 47583, 
'downloader/request_count': 133, 
'downloader/request_method_count/GET': 133, 
'downloader/response_bytes': 3416996, 
'downloader/response_count': 130, 
'downloader/response_status_count/200': 95, 
'downloader/response_status_count/301': 24, 
'downloader/response_status_count/302': 8, 
'downloader/response_status_count/500': 3, 
'finish_reason': 'finished'....} 

This answer से संबंधित है।

+0

बिल्कुल वही जो मैं खोज रहा हूं। मुझे लगता है कि यूआरएल जैसी विफलता जानकारी तक सुविधाजनक पहुंच प्रदान करने के लिए स्केप को इस सुविधा को जोड़ना चाहिए। – wlnirvana

+1

नवीनतम (1.0.5) संस्करण 'scrapy.contrib.downloadermiddleware.stats' –

+0

@ElRuso धन्यवाद पर बहिष्कृत करने के बजाय 'scrapy.downloadermiddlewares.stats' का उपयोग करें - – bahmait

6

स्केपर 0.24.6 के रूप में, alecxe द्वारा सुझाई गई विधि को प्रारंभिक URL के साथ त्रुटियां नहीं मिलेंगी। प्रारंभ URL के साथ त्रुटियों को रिकॉर्ड करने के लिए आपको parse_start_urls ओवरराइड करने की आवश्यकता है। इस उद्देश्य के लिए एलेक्सिस के उत्तर को अपनाने, आपको मिल जाएगा:

from scrapy.selector import HtmlXPathSelector 
from scrapy.contrib.spiders import CrawlSpider, Rule 
from scrapy.contrib.linkextractors.sgml import SgmlLinkExtractor 
from scrapy.item import Item, Field 

class GitHubLinkItem(Item): 
    url = Field() 
    referer = Field() 
    status = Field() 

class GithubHelpSpider(CrawlSpider): 
    name = "github_help" 
    allowed_domains = ["help.github.com"] 
    start_urls = ["https://help.github.com", ] 
    handle_httpstatus_list = [404] 
    rules = (Rule(SgmlLinkExtractor(), callback='parse_item', follow=True),) 

    def parse_start_url(self, response): 
     return self.handle_response(response) 

    def parse_item(self, response): 
     return self.handle_response(response) 

    def handle_response(self, response): 
     if response.status == 404: 
      item = GitHubLinkItem() 
      item['url'] = response.url 
      item['referer'] = response.request.headers.get('Referer') 
      item['status'] = response.status 

      return item 
5

यह इस प्रश्न पर एक अद्यतन है। मैं एक समान समस्या में भाग गया और मेरी पाइपलाइन में एक समारोह को कॉल करने के लिए स्केप सिग्नल का उपयोग करने की आवश्यकता थी। मैंने @ ताल्वालिन के कोड को संपादित किया है, लेकिन कुछ और स्पष्टता के लिए उत्तर देना चाहता था।

असल में, आपको हैंडल_स्पिडर_क्लोज्ड के लिए तर्क के रूप में स्वयं को जोड़ना चाहिए। आपको प्रेषक को इनिट में भी कॉल करना चाहिए ताकि आप स्पाइडर इंस्टेंस (स्वयं) को हैंडलिंग विधि में पास कर सकें।

from scrapy.spider import Spider 
from scrapy.xlib.pydispatch import dispatcher 
from scrapy import signals 

class MySpider(Spider): 
    handle_httpstatus_list = [404] 
    name = "myspider" 
    allowed_domains = ["example.com"] 
    start_urls = [ 
     'http://www.example.com/thisurlexists.html', 
     'http://www.example.com/thisurldoesnotexist.html', 
     'http://www.example.com/neitherdoesthisone.html' 
    ] 

    def __init__(self, category=None): 
     self.failed_urls = [] 
     # the dispatcher is now called in init 
     dispatcher.connect(self.handle_spider_closed,signals.spider_closed) 


    def parse(self, response): 
     if response.status == 404: 
      self.crawler.stats.inc_value('failed_url_count') 
      self.failed_urls.append(response.url) 

    def handle_spider_closed(self, spider, reason): # added self 
     self.crawler.stats.set_value('failed_urls',','.join(spider.failed_urls)) 

    def process_exception(self, response, exception, spider): 
     ex_class = "%s.%s" % (exception.__class__.__module__, exception.__class__.__name__) 
     self.crawler.stats.inc_value('downloader/exception_count', spider=spider) 
     self.crawler.stats.inc_value('downloader/exception_type_count/%s' % ex_class, spider=spider) 

मुझे आशा है कि यह भविष्य में किसी भी समस्या के साथ किसी को भी मदद करेगा।

8

स्कैपर डिफ़ॉल्ट रूप से 404 को अनदेखा करता है और पार्स नहीं करता है। 404 त्रुटि को संभालने के लिए यह करें। यह बहुत आसान है अगर आप जवाब में त्रुटि कोड 404 हो रही है, तो आप सेटिंग लिखें

HTTPERROR_ALLOWED_CODES = [404,403] 

में संभाल कर सकते हैं यह बहुत ही आसान तरीका के साथ है ..... और उसके बाद में प्रतिसाद स्थिति कोड को संभालने के अपने पार्स फ़ंक्शन

def parse(self,response): 
    if response.status == 404: 
     #your action on error 
सेटिंग्स में

और मिल पार्स समारोह में प्रतिक्रिया

0

इन उत्तरों से कुछ के अलावा, यदि आप मुड़ त्रुटियों ट्रैक करना चाहते हैं, मैं एक नज़र अनुरोध वस्तु की errback पैरामीटर का उपयोग करने पर ले जाएगा, जिस पर आप अनुरोध विफलता पर Twisted Failure के साथ कॉलबैक फ़ंक्शन सेट कर सकते हैं। यूआरएल के अतिरिक्त, यह विधि आपको विफलता के प्रकार को ट्रैक करने की अनुमति दे सकती है।

फिर आप का उपयोग करके यूआरएल प्रवेश कर सकते हैं: failure.request.url (जहां failure मुड़ Failure वस्तु errback में पारित कर दिया है)।

# these would be in a Spider 
def start_requests(self): 
    for url in self.start_urls: 
     yield scrapy.Request(url, callback=self.parse, 
            errback=self.handle_error) 

def handle_error(self, failure): 
    url = failure.request.url 
    logging.error('Failure type: %s, URL: %s', failure.type, 
               url) 

Scrapy डॉक्स, यह कैसे किया जा सकता है की एक पूरी उदाहरण दे, सिवाय इसके कि Scrapy लकड़हारा के लिए कॉल अब कर रहे हैं depreciated, तो मैं पायथन के logging में निर्मित) का उपयोग करने के लिए अपने उदाहरण अनुकूलित किया है:

https://doc.scrapy.org/en/latest/topics/request-response.html#topics-request-response-ref-errbacks

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