Как обработать ошибку подключения или загрузки в Scrapy? - PullRequest
0 голосов
/ 11 октября 2018

Я использую следующее для проверки (интернет) ошибок подключения в моем spider.py:

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):
    if failure.check(DNSLookupError):   # or failure.check(UnknownHostError):
        request = failure.request
        self.logger.error('DNSLookupError on: %s', request.url)
        print("\nDNS Error! Please check your internet connection!\n")

    elif failure.check(HttpError):
        response = failure.value.response
        self.logger.error('HttpError on: %s', response.url)

    print('\nSpider closed because of Connection issues!\n')
    raise CloseSpider('Because of Connection issues!')
    ...

Однако, когда работает паук, и соединение не работает, я все равно получаю Traceback (most recent call last): сообщений.Я хотел бы избавиться от этого, обработав ошибку и правильно отключив паука.

Вывод, который я получаю:

2018-10-11 12:52:15 [NewAds] ERROR: DNSLookupError on: https://x.com

DNS Error! Please check your internet connection!

2018-10-11 12:52:15 [scrapy.core.scraper] ERROR: Error downloading <GET https://x.com>

Traceback (most recent call last):
  File "/usr/lib/python3.6/site-packages/twisted/internet/defer.py", line 1384, in _inlineCallbacks
    result = result.throwExceptionIntoGenerator(g)
  File "/usr/lib/python3.6/site-packages/twisted/python/failure.py", line 408, in throwExceptionIntoGenerator
    return g.throw(self.type, self.value, self.tb)
  File "/usr/lib/python3.6/site-packages/scrapy/core/downloader/middleware.py", line 43, in process_request
    defer.returnValue((yield download_func(request=request,spider=spider)))
  File "/usr/lib/python3.6/site-packages/twisted/internet/defer.py", line 653, in _runCallbacks
    current.result = callback(current.result, *args, **kw)
  File "/usr/lib/python3.6/site-packages/twisted/internet/endpoints.py", line 954, in startConnectionAttempts
    "no results for hostname lookup: {}".format(self._hostStr)

twisted.internet.error.DNSLookupError: DNS lookup failed: no results for hostname lookup: x.com.

Из этого вы можете заметить следующее:

  1. Я могу частично обработать (первую?) DNSLookupError ошибку, но ...
  2. выключение паука не кажется достаточно быстрым, поэтому паук продолжает пытаться загрузитьURL, вызывающий другую ошибку (ERROR: Error downloading).
  3. , возможно, вызывающий 2-ю ошибку: twisted.internet.error.DNSLookupError:?

Как я могу обработать [scrapy.core.scraper] ERROR: Error downloading и сделатьВы уверены, что паук правильно отключился?

(Или: Как проверить интернет-соединение при запуске паука? )

1 Ответ

0 голосов
/ 11 октября 2018

Хорошо, я пытался играть со Scrapy, стараясь изящно выйти, когда нет подключения к интернету или другая ошибка.Результат?Я не мог заставить его работать должным образом.Вместо этого я закончил тем, что просто отключил весь переводчик и всех его отвратительных детей с отсрочкой, используя os._exit(0), например:

import socket
#from scrapy.exceptions import CloseSpider
...
def check_connection(self):
    try:
        socket.create_connection(("www.google.com", 443))
        return True
    except:
        pass
    return False

def start_requests(self):
    if not self.check_connection(): 
        print('Connection Lost! Please check your internet connection!', flush=True)
        os._exit(0)                     # Kill Everything
        #CloseSpider('Grace Me!')       # Close clean but expect deferred errors!
        #raise CloseSpider('No Grace')  # Raise Exception (w. Traceback)?!
    ...

Вот и все!


ПРИМЕЧАНИЕ

Я пытался использовать различные внутренние методы для выключения Scrapy и справлялся с неприятной:

[scrapy.core.scraper] ERROR: Error downloading

проблемой.Это только (?) Происходит, когда вы используете: raise CloseSpider('Because of Connection issues!') среди многих других попыток.Снова следует twisted.internet.error.DNSLookupError, хотя я и обработал это в моем коде, похоже, он появился из ниоткуда.Очевидно, raise - это ручной способ всегда выдавать исключение .Так что вместо этого используйте CloseSpider() без него.


Данная проблема также, кажется, является повторяющейся проблемой в среде Scrapy ... и фактически в исходном коде есть некоторые FIXME там .Даже когда я пытался применить такие вещи, как:

def stop(self):
    self.deferred = defer.Deferred()
    for name, signal in vars(signals).items():
        if not name.startswith('_'):
            disconnect_all(signal)
    self.deferred.callback(None)

и используя эти ...

#self.stop()
#sys.exit()
#disconnect_all(signal, **kwargs)
#self.crawler.engine.close_spider(spider, 'cancelled')
#scrapy.crawler.CrawlerRunner.stop()
#crawler.signals.stop()

PS.Было бы здорово, если бы разработчики Scrapy могли документировать, как лучше всего справиться с таким простым делом, как отсутствие интернет-соединения?

...