ロギング(logging)

注釈

scrapy.log は、Python標準ロギングの明示的な呼び出しを支援する機能とともに非推奨になりました。 新しいロギングシステムの詳細については、以下をご覧ください。

Scrapyは、イベント・ロギングに logging を使用します。 始めるための簡単な例をいくつか紹介しますが、より高度なユース・ケースについては、Pythonの組み込みロギング・システムのドキュメントを徹底的に読むことを強くお勧めします。

ロギングはそのままで機能し、 ロギング設定 にリストされているScrapy設定である程度設定できます。

Scrapyは scrapy.utils.log.configure_logging() を呼び出していくつかの妥当なデフォルトを設定し、コマンドを実行するときに ロギング設定 でそれらの設定を処理するため、スクリプトからScrapyを実行する で説明されているスクリプトからScrapyを実行している場合は、手動で呼び出すことをお勧めします。

ログ・レベル

Pythonの組み込みロギングは、特定のログメッセージの重大度を示す5つの異なるレベルを定義します。 以下は標準のもので、降順でリストされています:

  1. logging.CRITICAL - 致命的なエラーの場合(最高の重要度)

  2. logging.ERROR - 通常のエラーの場合

  3. logging.WARNING - 警告メッセージの場合

  4. logging.INFO - 情報メッセージ用

  5. logging.DEBUG - デバッグメッセージ用(最も低い重要度)

メッセージをログ出しする方法

logging.WARNING レベルを使用してメッセージをログ出しする方法の簡単な例を次に示します:

import logging
logging.warning("This is a warning")

標準の5つのレベルのいずれかでログメッセージを発行するためのショートカットがあり、引数として指定されたレベルを取る一般的な logging.log メソッドもあります。必要に応じて、さっきの例を次のように書き換えることができます:

import logging
logging.log(logging.WARNING, "This is a warning")

さらに、あなたはメッセージをカプセル化するためのさまざまなロガーを作成できます。(たとえば、一般的な方法は、モジュールごとに異なるロガーを作成することです)。 これらのロガーは独立して構成でき、階層構造が可能です。

前の例では、舞台裏でルート・ロガーを使用します。これは、特に指定がない限り、すべてのメッセージが伝播されるトップ・レベル・ロガーです。 logging ヘルパーの使用は、ルート・ロガーを明示的に取得するための単なるショートカットであるため、これは最後のコード片と同等です。

import logging
logger = logging.getLogger()
logger.warning("This is a warning")

logging.getLogger 関数で名前を取得するだけで、異なるロガーを使用できます:

import logging
logger = logging.getLogger('mycustomlogger')
logger.warning("This is a warning")

最後に、 __name__ 変数を使用して、作業中のモジュールのカスタム・ロガーを確保できます。これには、現在のモジュールのパスが入力されます:

import logging
logger = logging.getLogger(__name__)
logger.warning("This is a warning")

参考

モジュール・ロギング HowTo

基本ロギング・チュートリアル(https://docs.python.org/2/howto/logging.html)

モジュール・ロギング、 Loggers

ロガーに関する詳細なドキュメント(https://docs.python.org/2/library/logging.html#logger-objects)

スパイダーからのロギング

Scrapyは、各スパイダー・インスタンス内で logger を提供します。

import scrapy

class MySpider(scrapy.Spider):

    name = 'myspider'
    start_urls = ['https://scrapy.org']

    def parse(self, response):
        self.logger.info('Parse function called on %s', response.url)

そのロガーはスパイダーの名前を使用して作成されますが、任意のカスタムPythonロガーを使用できます。 例えば以下です:

import logging
import scrapy

logger = logging.getLogger('mycustomlogger')

class MySpider(scrapy.Spider):

    name = 'myspider'
    start_urls = ['https://scrapy.org']

    def parse(self, response):
        logger.info('Parse function called on %s', response.url)

ロギング構成(configuration)

ロガー自身は、ロガーを介して送信されたメッセージの表示方法を管理しません。 このタスクでは、さまざまなハンドラーを任意のロガー・インスタンスにアタッチして、それらのメッセージを標準出力、ファイル、電子メールなどの適切な宛先にリダイレクトします。

デフォルトでは、Scrapyは以下の設定に基づいて、ルート・ロガーのハンドラーを設定および構成します。

ロギング設定

これらの設定は、ロギングの構成(configuration)に使用できます:

最初のいくつかの設定は、ログメッセージの宛先を定義します。 LOG_FILE が設定されている場合、ルート・ロガーを介して送信されたメッセージは LOG_ENCODING エンコーディングで LOG_FILE という名前のファイルにリダイレクトされます。設定が解除され、 LOG_ENABLEDTrue の場合、ログメッセージは標準エラーに表示されます。 そして、 LOG_ENABLEDFalse の場合、目に見えるログ出力はありません。

LOG_LEVEL は表示する重大度の最小レベルを決定し、指定より重大度の低いメッセージは除外されます。 ログ・レベル にリストされている可能なレベルを範囲としています。

LOG_FORMATLOG_DATEFORMAT は、すべてのメッセージのレイアウトとして使用されるフォーマット文字列を指定します。これらの文字列には、 それぞれ、 ロギングのログ・レコード属性文書 や、 日時のstrftimeおよびstrptimeディレクティブ にリストされているプレース・ホルダーを含めることができます。

LOG_SHORT_NAMES が設定されている場合、ログはログを印刷するScrapyコンポーネントを表示しません。 デフォルトでは設定されていないため、ログにはそのログ出力の原因となるScrapyコンポーネントが含まれています。

コマンド・ライン・オプション

すべてのコマンドで使用できるコマンドライン引数があり、これを使用してロギングに関するScrapy設定の一部をオーバーライドできます。

  • --logfile FILE

    LOG_FILE をオーバーライドする

  • --loglevel/-L LEVEL

    LOG_LEVEL をオーバーライドする

  • --nolog

    LOG_ENABLEDFalse に設定

参考

モジュール logging.handlers

利用可能なハンドラーに関する詳細なドキュメント

カスタム・ログ書式

LogFormatter クラスを拡張し、 LOG_FORMATTER が新しいクラスを指すようにすることで、さまざまなアクションに対してカスタム・ログ形式を設定できます。

class scrapy.logformatter.LogFormatter[ソース]

さまざまなアクションのログメッセージを生成するためのクラス。

すべてのメソッドは、パラメーター levelmsgargs をリストする辞書を返さなければなりません。これらは、 logging.log を呼び出すときにログ・メッセージを作成するために使用されます。

メソッド出力の辞書キー:

  • level はそのアクションのログ・レベルです。 python logging library のログレベルを使用できます。それは logging.DEBUGlogging.INFOlogging.WARNINGlogging.ERRORlogging.CRITICAL です。

  • msg は異なるフォーマットのプレース・ホルダーを含むことができる文字列でなければなりません。 提供された args でフォーマットされたこの文字列は、そのアクションの長いメッセージになります。

  • args は、 msg のフォーマット・プレース・ホルダーを持つタプルまたは辞書である必要があります。最終的なログメッセージは msg % args として処理されます。

各アクションのログ方法をカスタマイズしたい場合、または完全に省略したい場合、ユーザーは独自の LogFormatter クラスを定義できます。 アクションのロギングを省略するには、メソッドは None を返す必要があります。

アイテムがパイプラインからドロップされたときにログ・メッセージの重大度を下げるためにカスタム・ログ・フォーマッタを作成する方法の例を次に示します:

class PoliteLogFormatter(logformatter.LogFormatter):
    def dropped(self, item, exception, response, spider):
        return {
            'level': logging.INFO, # lowering the level from logging.WARNING
            'msg': "Dropped: %(exception)s" + os.linesep + "%(item)s",
            'args': {
                'exception': exception,
                'item': item,
            }
        }
crawled(request, response, spider)[ソース]

クローラーがWebページを見つけたときにメッセージをログ出力します。

download_error(failure, request, spider, errmsg=None)[ソース]

スパイダーからのダウンロード・エラー・メッセージをログに記録します(通常はエンジンから送信されます)。

バージョン 2.0 で追加.

dropped(item, exception, response, spider)[ソース]

アイテムがアイテム・パイプラインを通過中にドロップされたときにメッセージをrログ出力します。

item_error(item, exception, response, spider)[ソース]

アイテムがアイテム・パイプラインを通過しているときにアイテムがエラーを引き起こしたときメッセージをログに記録します。

バージョン 2.0 で追加.

scraped(item, response, spider)[ソース]

アイテムがスパイダーによってスクレイプされたときにメッセージをログ出力します。

spider_error(failure, request, response, spider)[ソース]

スパイダーからのエラーメッセージをログに記録します。

バージョン 2.0 で追加.

高度なカスタマイズ

Scrapyはstdlibロギング・モジュールを使用するため、stdlibロギングのすべての機能を使用してロギングをカスタマイズできます。

たとえば、多くの「HTTP 404」や「HTTP 500」のレスポンスを返すWebサイトをスクレイピングしていて、このようなすべてのメッセージを非表示にしたいとします:

2016-12-16 22:00:06 [scrapy.spidermiddlewares.httperror] INFO: Ignoring
response <500 http://quotes.toscrape.com/page/1-34/>: HTTP status code
is not handled or not allowed

最初に注意することはロガー名です。角括弧内に書きます。 [scrapy.spidermiddlewares.httperror] 。単に [scrapy] を取得した場合、 LOG_SHORT_NAMES はおそらくTrueに設定されています。Falseに設定して、クロールを再実行します。

次に、メッセージにINFOレベルがあることがわかります。非表示にするには、INFOよりも高い scrapy.spidermiddlewares.httperror のログ・レベルを設定する必要があります。 INFOの次のレベルはWARNINGです。 スパイダー __init__ メソッド内でその設定を行うことができます:

import logging
import scrapy


class MySpider(scrapy.Spider):
    # ...
    def __init__(self, *args, **kwargs):
        logger = logging.getLogger('scrapy.spidermiddlewares.httperror')
        logger.setLevel(logging.WARNING)
        super().__init__(*args, **kwargs)

あなたがこのスパイダーを再度実行すると、 scrapy.spidermiddlewares.httperror ロガーからのINFOメッセージはなくなります。

LogRecord データでログ・レコードをフィルタリングすることもできます。 たとえば、文字列の部分(substring)または正規表現を使用して、メッセージの内容でログ・レコードをフィルタリングできます。 logging.Filter サブ・クラスを作成し、正規表現パターンを装備して不要なメッセージを除外します:

import logging
import re

class ContentFilter(logging.Filter):
    def filter(self, record):
        match = re.search(r'\d{3} [Ee]rror, retrying', record.message)
        if match:
            return False

Scrapyによって作成されたルート・ハンドラーにプロジェクト・レベルのフィルターをアタッチできます。これは、プロジェクトのさまざまな部分(ミドルウェア、スパイダーなど)のすべてのロガーをフィルタ処理するための便利な方法です:

import logging
import scrapy

class MySpider(scrapy.Spider):
    # ...
    def __init__(self, *args, **kwargs):
        for handler in logging.root.handlers:
            handler.addFilter(ContentFilter())

または、特定のロガーを選択して、他のロガーに影響を与えずに非表示にすることもできます:

import logging
import scrapy

class MySpider(scrapy.Spider):
    # ...
    def __init__(self, *args, **kwargs):
        logger = logging.getLogger('my_logger')
        logger.addFilter(ContentFilter())

scrapy.utils.logモジュール

scrapy.utils.log.configure_logging(settings=None, install_root_handler=True)[ソース]

Scrapyのロギングのデフォルトを初期化します。

パラメータ
  • settings (dict, Settings object or None) -- ルートロガーのハンドラーの作成と設定に使用される設定(デフォルト: None)。

  • install_root_handler (bool) -- ルート・ロギング・ハンドラーをインストールするかどうか(デフォルト: True)

この関数は以下のとおり動作します:

  • Pythonの標準ログを介したルーティング警告とtwistedのロギング

  • ScrapyおよびTwistedロガーにそれぞれDEBUGおよびERRORレベルを割り当てます

  • LOG_STDOUT設定がTrueの場合、ログは標準出力に出力されます。

install_root_handler がTrue(デフォルト)の場合、この関数は与えられた設定( ロギング設定 参照)に従ってルート・ロガーのハンドラーも作成します。 settings 引数を使用してデフォルトのオプションを上書きできます。 settings が空またはNoneの場合、デフォルトが使用されます。

configure_logging はScrapyコマンドまたは CrawlerProcess を使用すると自動的に呼び出されますが、 CrawlerRunner を使用してカスタム・スクリプトを実行する場合は明示的に呼び出す必要があります。その場合、その使用は必須ではありませんが、推奨されます。

カスタム・スクリプトを実行するときのもう1つのオプションは、ログを手動で構成することです。 これを行う時は、 logging.basicConfig() を使用して基本的なルート・ハンドラーを設定できます。

CrawlerProcess は自動的に configure_logging を呼び出すため、 CrawlerRunner と一緒に logging.basicConfig() のみを使用することをお勧めします。

以下は、INFO のメッセージをファイルにリダイレクトする方法の例です:

import logging

logging.basicConfig(
    filename='log.txt',
    format='%(levelname)s: %(message)s',
    level=logging.INFO
)

この方法でScrapyを使用する方法の詳細については、 スクリプトからScrapyを実行する を参照してください。