2016-04-03 2 views
0

Мой конкретный прецедент: У меня есть скребок, который очищает сайт, и как только элемент уступает - у меня есть связанный сигнал, который устанавливает ключ в Redis с истечением срока. В следующий раз, когда выполняется скребок, он должен игнорировать все URL-адреса, для которых существует ключ в Redis.Можно ли спокойно удалить запрос в Scrapy?

В первой части я работаю отлично; вторая часть - я создал DownloaderMiddleware, у которого есть функция process_request, которая смотрит на входящий объект запроса и проверяет, существует ли его URL в Redis. Если да, то raise s a IgnoreRequest исключение.

Что я хотел бы знать: Есть ли способ молча удалить запрос вместо того, чтобы поднимать исключение? Это не столько жесткое требование, сколько эстетическая вещь; Я не хочу видеть их в журналах ошибок - я хочу только увидеть ошибки bona-fide.

Я вижу в источнике Scrapy, что они используют то, что выглядит как ляп для дубликата фильтрации в основной планировщик (SCRAPY/ядро ​​/ scheduler.py):

def enqueue_request(self, request): 
    if not request.dont_filter and self.df.request_seen(request): 
     self.df.log(request, self.spider) 
     return False 
+1

Можете ли вы поделиться тем, что вы видите в журналах? и что вы хотели бы иметь вместо этого? О фильтрации дубликатов по умолчанию по умолчанию действительно довольно просто, на основе [отпечатка пальца запроса (от канонического URL, метода HTTP, тела и заголовков необязательно) (https://github.com/scrapy/scrapy/blob/75cd056223a5a8da87a361aee42a541afcf27553/scrapy /utils/request.py#L19)), но [dupefilter настраивается] (http://doc.scrapy.org/en/latest/topics/settings.html?#std:setting-DUPEFILTER_CLASS). Если у вас есть идеи о том, как улучшить или упростить или прояснить дизайн, не стесняйтесь открывать дискуссию о Github. –

+0

ОШИБКА: Ошибка захвата обработчика сигнала: > Traceback (последний последний вызов): Файл «/Library/Python/2.7/site-packages/scrapy/utils/signal.py», строка 26, в send_catch_log * arguments, ** named) Файл «/Library/Python/2.7/site-packages/scrapy/xlib/pydispatch/robustapply.py», строка 57, в robustApply приемник возврата (* аргументы, ** названный) Файл «.../отложенные .py», строка 22, в process_request рейза IgnoreRequest ('URL откладывается') IgnoreRequest: URL отсрочена – infomaniac

+0

Мой промежуточный слой выглядит следующим образом: определение функции __init __ (самостоятельно, гусеничный): self.client = Redis () self.crawler = crawler self.crawler.signals.connect (self.process_request, signals.request_scheduled) Защиту process_request (я, запрос, паук): если не self.client.is_deferred (request.url): # URL не откладывается , продолжайте, как обычно, return None raise IgnoreRequest ('URL is offfer') ' – infomaniac

ответ

0

Scrapy использует модуль Python logging для регистрации вещей. Поскольку вы хотите всего лишь эстетическую вещь, вы можете написать logging filter, чтобы отфильтровать то, что вы не хотите видеть.

3

Middleware код из OP от комментариев

def __init__(self, crawler): 
    self.client = Redis() 
    self.crawler = crawler 
    self.crawler.signals.connect(self.process_request, signals.request_scheduled) 

def process_request(self, request, spider): 
    if not self.client.is_deferred(request.url): # URL is not deferred, proceed as normal 
     return None 
    raise IgnoreRequest('URL is deferred') 

Проблема с обработчик сигнала вы добавили на signals.request_scheduled. Если это вызывает исключение, it will appear in the logs

Я считаю, что некорректно (или не обязательно) регистрировать process_request в качестве обработчика сигналов здесь.

Я могу воспроизвести ваши ошибки консоли с этим подобным (некорректной) тест промежуточного слоя, который игнорируемых любой другой запрос, он видит:

from scrapy import log, signals 
from scrapy.exceptions import IgnoreRequest 

class TestMiddleware(object): 

    def __init__(self, crawler): 
     self.counter = 0 

    @classmethod 
    def from_crawler(cls, crawler): 
     o = cls(crawler) 
     crawler.signals.connect(o.open_spider, signals.spider_opened) 

     # this raises an exception always and will trigger errors in the console 
     crawler.signals.connect(o.process, signals.request_scheduled) 
     return o 

    def open_spider(self, spider): 
     spider.logger.info('TestMiddleware.open_spider()') 

    def process_request(self, request, spider): 
     spider.logger.info('TestMiddleware.process_request()') 
     self.counter += 1 
     if (self.counter % 2) == 0: 
      raise IgnoreRequest("ignoring request %d" % self.counter) 

    def process(self, *args, **kwargs): 
     raise Exception 

Посмотрите, что консоль говорит при запуске паука с этим промежуточное программное обеспечение:

2016-04-06 00:16:58 [scrapy] ERROR: Error caught on signal handler: <bound method ?.process of <mwtest.middlewares.TestMiddleware object at 0x7f83d4a73f50>> 
Traceback (most recent call last): 
    File "/home/paul/.virtualenvs/scrapy11rc3.py27/local/lib/python2.7/site-packages/scrapy/utils/signal.py", line 30, in send_catch_log 
    *arguments, **named) 
    File "/home/paul/.virtualenvs/scrapy11rc3.py27/local/lib/python2.7/site-packages/pydispatch/robustapply.py", line 55, in robustApply 
    return receiver(*arguments, **named) 
    File "/home/paul/tmp/mwtest/mwtest/middlewares.py", line 26, in process 
    raise Exception 
Exception 

code is here.

Сравните с этим:

$ cat middlewares.py 
from scrapy import log, signals 
from scrapy.exceptions import IgnoreRequest 

class TestMiddleware(object): 

    def __init__(self, crawler): 
     self.counter = 0 

    @classmethod 
    def from_crawler(cls, crawler): 
     o = cls(crawler) 
     crawler.signals.connect(o.open_spider, signals.spider_opened) 
     return o 

    def open_spider(self, spider): 
     spider.logger.info('TestMiddleware.open_spider()') 

    def process_request(self, request, spider): 
     spider.logger.info('TestMiddleware.process_request()') 
     self.counter += 1 
     if (self.counter % 2) == 0: 
      raise IgnoreRequest("ignoring request %d" % self.counter) 

IgnoreRequest не печатается в журналах, но у вас есть счетчики исключений в статистике в конце:

$ scrapy crawl httpbin 
2016-04-06 00:27:24 [scrapy] INFO: Scrapy 1.1.0rc3 started (bot: mwtest) 
(...) 
2016-04-06 00:27:24 [scrapy] INFO: Enabled downloader middlewares: 
['scrapy.downloadermiddlewares.httpauth.HttpAuthMiddleware', 
'scrapy.downloadermiddlewares.downloadtimeout.DownloadTimeoutMiddleware', 
'scrapy.downloadermiddlewares.useragent.UserAgentMiddleware', 
'scrapy.downloadermiddlewares.retry.RetryMiddleware', 
'mwtest.middlewares.TestMiddleware', 
'scrapy.downloadermiddlewares.defaultheaders.DefaultHeadersMiddleware', 
'scrapy.downloadermiddlewares.redirect.MetaRefreshMiddleware', 
'scrapy.downloadermiddlewares.httpcompression.HttpCompressionMiddleware', 
'scrapy.downloadermiddlewares.redirect.RedirectMiddleware', 
'scrapy.downloadermiddlewares.cookies.CookiesMiddleware', 
'scrapy.downloadermiddlewares.chunked.ChunkedTransferMiddleware', 
'scrapy.downloadermiddlewares.stats.DownloaderStats'] 
(...) 
2016-04-06 00:27:24 [scrapy] INFO: Spider opened 
2016-04-06 00:27:24 [scrapy] INFO: Crawled 0 pages (at 0 pages/min), scraped 0 items (at 0 items/min) 
2016-04-06 00:27:24 [httpbin] INFO: TestMiddleware.open_spider() 
2016-04-06 00:27:24 [scrapy] DEBUG: Telnet console listening on 127.0.0.1:6023 
2016-04-06 00:27:24 [httpbin] INFO: TestMiddleware.process_request() 
2016-04-06 00:27:24 [httpbin] INFO: TestMiddleware.process_request() 
2016-04-06 00:27:24 [httpbin] INFO: TestMiddleware.process_request() 
2016-04-06 00:27:24 [httpbin] INFO: TestMiddleware.process_request() 
2016-04-06 00:27:24 [httpbin] INFO: TestMiddleware.process_request() 
2016-04-06 00:27:24 [scrapy] DEBUG: Crawled (200) <GET http://www.httpbin.org/user-agent> (referer: None) 
2016-04-06 00:27:25 [scrapy] DEBUG: Crawled (200) <GET http://www.httpbin.org/> (referer: None) 
2016-04-06 00:27:25 [scrapy] DEBUG: Crawled (200) <GET http://www.httpbin.org/headers> (referer: None) 
2016-04-06 00:27:25 [scrapy] INFO: Closing spider (finished) 
2016-04-06 00:27:25 [scrapy] INFO: Dumping Scrapy stats: 
{'downloader/exception_count': 2, 
'downloader/exception_type_count/scrapy.exceptions.IgnoreRequest': 2, 
'downloader/request_bytes': 665, 
'downloader/request_count': 3, 
'downloader/request_method_count/GET': 3, 
'downloader/response_bytes': 13006, 
'downloader/response_count': 3, 
'downloader/response_status_count/200': 3, 
'finish_reason': 'finished', 
'finish_time': datetime.datetime(2016, 4, 5, 22, 27, 25, 596652), 
'log_count/DEBUG': 4, 
'log_count/INFO': 13, 
'log_count/WARNING': 1, 
'response_received_count': 3, 
'scheduler/dequeued': 5, 
'scheduler/dequeued/memory': 5, 
'scheduler/enqueued': 5, 
'scheduler/enqueued/memory': 5, 
'start_time': datetime.datetime(2016, 4, 5, 22, 27, 24, 661345)} 
2016-04-06 00:27:25 [scrapy] INFO: Spider closed (finished) 
Смежные вопросы