29

我有一个scrapy项目,最终进入我的管道的项目相对较大,并且存储了大量元数据和内容。一切都在我的蜘蛛和管道中正常工作。然而,当它离开管道时,日志正在打印出整个scrapy Item(我相信):

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)

如果可以避免的话,我宁愿不要将所有这些数据都放入日志文件中。关于如何抑制此输出的任何建议?

4

8 回答 8

26

另一种方法是覆盖子类的__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例如,检查)。

于 2013-04-30T15:37:32.383 回答
17

阅读了文档并通过源代码进行了(简要)搜索,我看不到实现这一目标的直接方法。

锤子的做法是将settings中的日志级别设置为INFO(即在settings.py中加入以下行):

LOG_LEVEL='INFO'

这将删除有关正在抓取的 URL/页面的许多其他信息,但它肯定会抑制有关已处理项目的数据。

于 2013-01-18T02:02:16.667 回答
8

我尝试了@dino 提到的repre方式,效果不好。但是从他的想法演变而来,我尝试了str方法,并且它有效。

这是我的做法,非常简单:

    def __str__(self):
        return ""
于 2014-01-03T02:37:45.130 回答
6

如果您只想排除输出的某些属性,您可以扩展@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=(',', ': '))
于 2015-10-02T15:21:26.897 回答
5

如果您因为多年后遇到同样的问题而在这里找到了自己的方式,那么最简单的方法是使用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.

同样,您可以自定义已爬网页面和已删除项目的日志记录行为。

编辑:我在这个库中包装了这个格式化程序和一些其他的 Scrapy 东西。

于 2019-12-18T08:56:09.580 回答
4

或者如果您知道蜘蛛正常工作,那么您可以禁用整个日志记录

LOG_ENABLED = False

当我的爬虫运行良好时,我禁用它

于 2013-01-18T06:29:59.797 回答
3

我认为最干净的方法是向记录器添加一个过滤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())
于 2018-11-20T19:24:55.990 回答
1

我们在生产中使用以下示例:

import logging

logging.getLogger('scrapy.core.scraper').addFilter(
    lambda x: not x.getMessage().startswith('Scraped from'))

这是一个非常简单且有效的代码。我们将此代码添加到__init__.py带有蜘蛛的模块中。在这种情况下,此代码会自动使用类似scrapy crawl <spider_name>所有蜘蛛的命令运行。

于 2020-01-30T00:26:00.883 回答