scrapy 禁止在管道后在日志中打印报废项

5tmbdcev  于 2022-11-09  发布在  其他
关注(0)|答案(9)|浏览(133)

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

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)

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

i7uaboj4

i7uaboj41#

另一种方法是覆盖Item子类的__repr__方法,以选择性地选择在管道末尾打印哪些属性(如果有):

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)。

uyhoqukh

uyhoqukh2#

在通读了文档并对源代码进行了(简短的)搜索之后,我看不出有什么直接的方法可以实现这个目标。
Hammer方法是将设置中的日志记录级别设置为INFO(即将以下行添加到settings.py):
LOG_LEVEL='INFO'
这将剥离大量其他有关正在爬网的URL/页面的信息,但它肯定会抑制有关已处理项目的数据。

pinkon5k

pinkon5k3#

我尝试了@dino提到的repre方法,效果不太好。但从他的想法演变而来,我尝试了str方法,效果很好。
我是这样做的,非常简单:

def __str__(self):
        return ""
l3zydbqr

l3zydbqr4#

如果只想排除输出的某些属性,可以扩展@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=(',', ': '))
pwuypxnk

pwuypxnk5#

如果你是因为几年后遇到了同样的问题才找到这里的,那么最简单的方法就是使用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
同样地,您可以自订编目页面和舍弃项目的记录行为。

slmsl1lt

slmsl1lt6#

或者如果您知道spider工作正常,则可以禁用整个日志记录
LOG_ENABLED = False
当我的爬行器运行正常时,我会禁用它

pgvzfuti

pgvzfuti7#

我认为最简单的方法是在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())
3pvhb19x

3pvhb19x8#

我们在生产中使用以下样品:

import logging

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

这是一个非常简单的代码。我们在spider模块的__init__.py中添加了这段代码。在这种情况下,这段代码会自动运行,命令为scrapy crawl <spider_name>

sqyvllje

sqyvllje9#

创建筛选器:

class ItemFilter(logging.Filter):
    def filter(self, record):
        is_item_log = not record.msg.startswith('Scraped from')
        return is_item_log

然后将其添加到spider的__init__中。

class YourSpider(scrapy.Spider):
    name = "your_spider"

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

        if int(getattr(self, "no_items_output", 0)):
            for handler in logging.root.handlers:
                handler.addFilter(ItemFilter())

然后您可以运行scrapy crawl your_spider -a no_items_output=1

相关问题