2017-10-03 2 views
0

J'ai utilisé Scrapy dans un projet où j'ai mon propre format de journalisation json.outrepasser la journalisation scrapy esp. depuis middleware

Je veux éviter les stacktraces multi-lignes de Scrapy en particulier des middlewares comme celui de robots.txt. Je préférerais qu'il s'agisse d'une erreur d'une seule ligne ou de l'ensemble de la pile empilée dans un message. Comment puis-je désactiver ou remplacer ce comportement de journalisation?

Ci-dessous un échantillon stacktrace je suis arrivé d'un middleware de téléchargement robots.txt

2017-10-03 19:08:57 [scrapy.downloadermiddlewares.robotstxt] ERROR: Error downloading <GET http://www.somedomain.com/robots.txt>: DNS lookup failed: no results for hostname lookup: www.somedomain.com. Traceback (most recent call last): File "/Users/auser/.virtualenvs/myenv/lib/python3.5/site-packages/twisted/internet/defer.py", line 1384, in _inlineCallbacks 
    result = result.throwExceptionIntoGenerator(g) File "/Users/auser/.virtualenvs/myenv/lib/python3.5/site-packages/twisted/python/failure.py", line 393, in throwExceptionIntoGenerator 
    return g.throw(self.type, self.value, self.tb) File "/Users/auser/.virtualenvs/myenv/lib/python3.5/site-packages/scrapy/core/downloader/middleware.py", line 43, in process_request 
    defer.returnValue((yield download_func(request=request,spider=spider))) File "/Users/auser/.virtualenvs/myenv/lib/python3.5/site-packages/twisted/internet/defer.py", line 653, in _runCallbacks 
    current.result = callback(current.result, *args, **kw) File "/Users/auser/.virtualenvs/myenv/lib/python3.5/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: www.somedomain.com. 

Répondre

1

Je ne sais pas pourquoi ne pas comme un message d'erreur à plusieurs lignes (il est l'impression de retraçage de l'exception). Quoi qu'il en soit, nous pourrions personnaliser la mise en forme de la journalisation scrapy. En supposant que vous exécutiez vos scripts d'exploration par la ligne de commande scrapy, par exemple, scrapy crawl ou scrapy runspider. Voici un exemple de code (version python 3) qui montre comment utiliser votre propre formateur.

import logging 
import scrapy 


class OneLineFormatter(logging.Formatter): 

    def __init__(self, *args, **kwargs): 
     super(OneLineFormatter, self).__init__(*args, **kwargs) 

    def format(self, record): 
     formatted = super(OneLineFormatter, self).format(record) 
     return formatted.replace('\n', ' ') 


class TestSpider(scrapy.Spider): 
    name = "test" 
    start_urls = [ 
     'http://www.somenxdomain.com/robots.txt', 
    ] 

    def __init__(self, fmt, datefmt, *args, **kwargs): 
     my_formatter = OneLineFormatter(fmt=fmt, datefmt=datefmt) 
     root = logging.getLogger() 
     for h in root.handlers: 
      h.setFormatter(my_formatter) 
     super(TestSpider, self).__init__(*args, **kwargs) 

    @classmethod 
    def from_crawler(cls, crawler): 
     settings = crawler.settings 
     return cls(settings.get('LOG_FORMAT'), settings.get('LOG_DATEFORMAT')) 

    def parse(self, response): 
     pass 

Et voici quelques explications.

  1. Flux de travail de journalisation Python. Le scrapy lui-même utilise le système de journalisation intégré python. Ainsi, vous avez besoin de quelques connaissances de base de la journalisation python, en particulier les relations entre les classes Logger, Handler, Filter et Formatter. Je suggère fortement le working flow de journalisation python.

  2. Scrapy journalisation et paramètres. Si votre araignée est exécutée par la ligne de commande scrapy, par exemple, scrapy crawl ou scrapy runspider, la fonction scrapy [configure_logging](https://docs.python.org/2/howto/logging.html#logging-flow) est appelée pour initialiser la journalisation. L'instruction de scrapy logging pourrait donner quelques instructions sur la façon de personnaliser votre journalisation et par scrapy settings vous pourriez accéder à vos paramètres.

  3. Comment l'exemple de code fonctionne. Le flux de travail de base est:

    • D'abord, vous devez définir votre propre classe de formatage pour personnaliser la mise en forme de la journalisation. Deuxièmement, dans votre araignée, vous devez avoir accès à vos paramètres de formatage pour initialiser votre classe de formateur.
    • Et enfin, dans votre araignée, vous obtenez le logger root et définissez votre formateur à tous les gestionnaires de root.

Si vous écrivez votre propre script et utilisez scrapy comme API, voir [exécuter scrapy partir d'un script] (https://doc.scrapy.org/en/latest/topics/practices.html#run-scrapy-from-a-script), vous devez configurer l'enregistrement de votre auto.

Le formateur ci-dessus ne fonctionnera pas tant que l'araignée n'aura pas été initialisée. Voici quelques tirages:

2017-10-03 11:59:39 [scrapy.utils.log] INFO: Scrapy 1.3.3 started (bot: scrapybot) 
2017-10-03 11:59:39 [scrapy.utils.log] INFO: Overridden settings: {'SPIDER_LOADER_WARN_ONLY': True} 
2017-10-03 11:59:39 [scrapy.middleware] INFO: Enabled extensions: 
['scrapy.extensions.corestats.CoreStats', 
'scrapy.extensions.telnet.TelnetConsole', 
'scrapy.extensions.logstats.LogStats'] 
2017-10-03 11:59:39 [scrapy.middleware] INFO: Enabled downloader middlewares: ['scrapy.downloadermiddlewares.httpauth.HttpAuthMiddleware', 'scrapy.downloadermiddlewares.downloadtimeout.DownloadTimeoutMiddleware', 'scrapy.downloadermiddlewares.defaultheaders.DefaultHeadersMiddleware', 'scrapy.downloadermiddlewares.useragent.UserAgentMiddleware', 'scrapy.downloadermiddlewares.retry.RetryMiddleware', 'scrapy.downloadermiddlewares.redirect.MetaRefreshMiddleware', 'scrapy.downloadermiddlewares.httpcompression.HttpCompressionMiddleware', 'scrapy.downloadermiddlewares.redirect.RedirectMiddleware', 'scrapy.downloadermiddlewares.cookies.CookiesMiddleware', 'scrapy.downloadermiddlewares.stats.DownloaderStats'] 
2017-10-03 11:59:39 [scrapy.middleware] INFO: Enabled spider middlewares: ['scrapy.spidermiddlewares.httperror.HttpErrorMiddleware', 'scrapy.spidermiddlewares.offsite.OffsiteMiddleware', 'scrapy.spidermiddlewares.referer.RefererMiddleware', 'scrapy.spidermiddlewares.urllength.UrlLengthMiddleware', 'scrapy.spidermiddlewares.depth.DepthMiddleware'] 
2017-10-03 11:59:39 [scrapy.middleware] INFO: Enabled item pipelines: [] 
2017-10-03 11:59:39 [scrapy.core.engine] INFO: Spider opened 
2017-10-03 11:59:39 [scrapy.extensions.logstats] INFO: Crawled 0 pages (at 0 pages/min), scraped 0 items (at 0 items/min) 
2017-10-03 11:59:39 [scrapy.extensions.telnet] DEBUG: Telnet console listening on 127.0.0.1:6024 
2017-10-03 11:59:39 [scrapy.downloadermiddlewares.retry] DEBUG: Retrying <GET http://www.somenxdomain.com/robots.txt> (failed 1 times): DNS lookup failed: no results for hostname lookup: www.somenxdomain.com. 
2017-10-03 11:59:39 [scrapy.downloadermiddlewares.retry] DEBUG: Retrying <GET http://www.somenxdomain.com/robots.txt> (failed 2 times): DNS lookup failed: no results for hostname lookup: www.somenxdomain.com. 
2017-10-03 11:59:39 [scrapy.downloadermiddlewares.retry] DEBUG: Gave up retrying <GET http://www.somenxdomain.com/robots.txt> (failed 3 times): DNS lookup failed: no results for hostname lookup: www.somenxdomain.com. 
2017-10-03 11:59:39 [scrapy.core.scraper] ERROR: Error downloading <GET http://www.somenxdomain.com/robots.txt> Traceback (most recent call last): File "/Users/xxx/anaconda/envs/p3/lib/python3.6/site-packages/twisted/internet/defer.py", line 1384, in _inlineCallbacks  result = result.throwExceptionIntoGenerator(g) File "/Users/xxx/anaconda/envs/p3/lib/python3.6/site-packages/twisted/python/failure.py", line 393, in throwExceptionIntoGenerator  return g.throw(self.type, self.value, self.tb) File "/Users/xxx/anaconda/envs/p3/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 "/Users/xxx/anaconda/envs/p3/lib/python3.6/site-packages/twisted/internet/defer.py", line 653, in _runCallbacks  current.result = callback(current.result, *args, **kw) File "/Users/xxx/anaconda/envs/p3/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: www.somenxdomain.com. 
2017-10-03 11:59:40 [scrapy.core.engine] INFO: Closing spider (finished) 
2017-10-03 11:59:40 [scrapy.statscollectors] INFO: Dumping Scrapy stats: {'downloader/exception_count': 3, 'downloader/exception_type_count/twisted.internet.error.DNSLookupError': 3, 'downloader/request_bytes': 684, 'downloader/request_count': 3, 'downloader/request_method_count/GET': 3, 'finish_reason': 'finished', 'finish_time': datetime.datetime(2017, 10, 3, 15, 59, 40, 46636), 'log_count/DEBUG': 4, 'log_count/ERROR': 1, 'log_count/INFO': 7, 'scheduler/dequeued': 3, 'scheduler/dequeued/memory': 3, 'scheduler/enqueued': 3, 'scheduler/enqueued/memory': 3, 'start_time': datetime.datetime(2017, 10, 3, 15, 59, 39, 793795)} 
2017-10-03 11:59:40 [scrapy.core.engine] INFO: Spider closed (finished) 

Vous pouvez voir qu'après l'exécution de spider, tous les messages sont formatter en une ligne. (En supprimant '\n').

Espérons que cela serait utile.

+0

super merci. J'ai upvoted la réponse, mais l'acceptera une fois que j'ai fini d'utiliser la solution. – comiventor