我有一个scrapy项目,最终进入我的管道的项目相对较大,并存储了大量的元数据和内容。我的蜘蛛和管道中的一切都正常。但是,日志会在离开管道时打印出整个scrapy项目(我相信):
2013-01-17 18:42:17-0600 [tutorial] DEBUG: processing Pipeline pipeline module
2013-01-17 18:42:17-0600 [tutorial] DEBUG: Scraped from <200 http://www.example.com>
{'attr1': 'value1',
'attr2': 'value2',
'attr3': 'value3',
...
snip
...
'attrN': 'valueN'}
2013-01-17 18:42:18-0600 [tutorial] INFO: Closing spider (finished)
如果可以避免,我宁愿不把所有这些数据都写进日志文件中。有关如何抑制此输出的任何建议?
答案 0 :(得分:19)
另一种方法是覆盖__repr__
子类的Item
方法,以选择性地选择在管道末尾打印哪些属性(如果有):
from scrapy.item import Item, Field
class MyItem(Item):
attr1 = Field()
attr2 = Field()
# ...
attrN = Field()
def __repr__(self):
"""only print out attr1 after exiting the Pipeline"""
return repr({"attr1": self.attr1})
这样,您可以将日志级别保持在DEBUG
,并仅显示要从管道中看到的属性(例如,检查attr1
)。
答案 1 :(得分:9)
通过阅读文档并对源代码进行(简短)搜索,我看不到实现此目标的简单方法。
锤子方法是将设置中的日志记录级别设置为INFO(即将以下行添加到settings.py):
LOG_LEVEL='INFO'
这将删除有关正在抓取的网址/网页的大量其他信息,但它肯定会取消有关已处理项目的数据。
答案 2 :(得分:8)
我尝试了@dino提到的代表方式,但效果不佳。但是从他的想法演变而来,我尝试了 str 方法,并且它有效。
我是这样做的,非常简单:
def __str__(self):
return ""
答案 3 :(得分:4)
如果只想排除输出的某些属性,可以扩展@dino
给出的答案from scrapy.item import Item, Field
import json
class MyItem(Item):
attr1 = Field()
attr2 = Field()
attr1ToExclude = Field()
attr2ToExclude = Field()
# ...
attrN = Field()
def __repr__(self):
r = {}
for attr, value in self.__dict__['_values'].iteritems():
if attr not in ['attr1ToExclude', 'attr2ToExclude']:
r[attr] = value
return json.dumps(r, sort_keys=True, indent=4, separators=(',', ': '))
答案 4 :(得分:2)
或者如果您知道蜘蛛工作正常,则可以禁用整个日志记录
LOG_ENABLED = False
当我的抓取工具运行良好时,我禁用了
答案 5 :(得分:1)
我认为最干净的方法是向scrapy.core.scraper
记录器添加一个过滤器,以更改相关消息。这使您可以保持项目__repr__
的完整性,而不必更改scrapy的日志记录级别:
import re
class ItemMessageFilter(logging.Filter):
def filter(self, record):
# The message that logs the item actually has raw % operators in it,
# which Scrapy presumably formats later on
match = re.search(r'(Scraped from %\(src\)s)\n%\(item\)s', record.msg)
if match:
# Make the message everything but the item itself
record.msg = match.group(1)
# Don't actually want to filter out this record, so always return 1
return 1
logging.getLogger('scrapy.core.scraper').addFilter(ItemMessageFilter())
答案 6 :(得分:1)
我们在生产中使用以下示例:
import logging
logging.getLogger('scrapy.core.scraper').addFilter(
lambda x: not x.getMessage().startswith('Scraped from'))
这是一个非常简单且有效的代码。我们将此代码添加到带有蜘蛛程序的__init__.py
模块中。在这种情况下,该代码会针对所有蜘蛛自动以scrapy crawl <spider_name>
之类的命令运行。
答案 7 :(得分:0)
如果您由于几年后遇到相同的问题而在这里找到自己的出路,那么最简单的方法是使用LogFormatter
:
class QuietLogFormatter(scrapy.logformatter.LogFormatter):
def scraped(self, item, response, spider):
return (
super().scraped(item, response, spider)
if spider.settings.getbool("LOG_SCRAPED_ITEMS")
else None
)
只需将LOG_FORMATTER = "path.to.QuietLogFormatter"
添加到您的settings.py
中,您将看到所有DEBUG
消息,但已刮除的项目除外。使用LOG_SCRAPED_ITEMS = True
,您可以恢复以前的行为,而不必更改LOG_FORMATTER
。
类似地,您可以自定义已爬网页面和已删除项目的日志记录行为。