Scarnox · Blog

スクレイピング時にcaptchaを避ける方法(ルールを守ったまま)

スクレイピング中のcaptchaのほとんどは、自動化されたトラフィックに見えるアクセスへの反応です。もっとも安価な対策は、captchaを引き起こさないことです。そのためには、まず正規のデータソースを探し、サイトのルールで許可されている範囲を確認し、リクエストの数を減らして間隔を広げ、同じページを二度取得しないことが必要です。captchaを解くのは、避けられない場合の最後の手段であり、基本の計画ではありません。

まず公式APIやフィードを確認する

スクレイピングされることの多いサイトの多くは、captchaなしで同じデータを取得する方法をすでに提供しています。公開APIやデータエクスポート、RSSやサイトマップのフィード、パートナープログラムなどです。公式のデータソースのほうが信頼性が高く、予告なしに変わりにくく、サイトの運営者がどのように利用されるかを決められます。次のようなものを探してください。

必要なデータがこれらでまかなえるなら、それを使ってください。HTMLをまったくリクエストしなければ、captchaのほとんどは避けられます。

robots.txtと要求されている間隔を守る

robots.txtには、自動化されたクライアントが取得してよいパスと、場合によってはリクエスト間で待つべき時間が書かれています。Pythonの標準ライブラリで読み込めます。

import time
from urllib.robotparser import RobotFileParser
import requests

USER_AGENT = "ExampleBot/1.0 (+https://example.com/bot)"

parser = RobotFileParser()
parser.set_url("https://example.com/robots.txt")
parser.read()

delay = parser.crawl_delay(USER_AGENT) or 5  # 保守的に5秒をデフォルトにする
urls = [
    "https://example.com/products?page=1",
    "https://example.com/products?page=2",
]

last_request = 0.0
for url in urls:
    if not parser.can_fetch(USER_AGENT, url):
        print("skipped by robots.txt:", url)
        continue
    wait = delay - (time.monotonic() - last_request)
    if wait > 0:
        time.sleep(wait)
    resp = requests.get(url, headers={"User-Agent": USER_AGENT}, timeout=30)
    last_request = time.monotonic()
    print(url, resp.status_code)

robots.txtがパスを禁止している場合、正直な答えは、そのパスには触れないことか、運営者に相談することです。ブラウザを使って迂回しても、サイトが求めた内容は変わりません。

速度を落として、リクエストを分散する

一定の控えめなペースであればチャレンジが出ることはほとんどありませんが、バーストは大抵チャレンジを引き起こします。次のような習慣で大きく変わります。

キャッシュして再取得しない

自分がしなかったリクエストは、サイトが処理しなくてよいリクエストです。取得したページは、取得日時とボディのハッシュとともに保存し、内容が変わった可能性が高いときだけ再取得してください。If-Modified-SinceやETagヘッダーによる条件付きリクエストに対応しているサーバーなら、「変更なし」を安価に返してもらえます。

セッションを再利用し、通常のヘッダーを送る

リクエストの間でCookieを保持するセッションは、毎回まっさらに始めるスクリプトより、訪問者に近い振る舞いになります。サイトごとにrequests.Session()を使い、ボットであることと連絡先が分かる、明確で正直なUser-Agentを送ってください。ルールを回避するためにブラウザを装ってはいけません。サイトの内容を表示するのにJavaScriptが必要な場合は、そのページだけブラウザツールを使い、同じレート制限を守ってください。

それでもcaptchaが出る場合

どれだけ注意深く振る舞っても、captchaが表示されるサイトはあります。コードでそれを検知し、ページを叩き続けるのではなく、そのジョブを止めてください。検知と、PopularCaptchaに対する任意の解決については、Webスクレイピングのcaptchaで扱っています。

クロールを開始前に計画する

毎日すべてを取得するクロールは、captchaを引き起こす最も簡単な方法です。作業を先に計画してください。

このような計画はリクエスト数を減らします。それが手元で最も効く手段です。

計画は、短い設定ファイルか表として書き出してください。サイト、セクション、更新間隔、そしてそれぞれの1日のリクエスト予算を書きます。予算を使い切ったら、次の時間枠まで作業を止めます。予算をガイドラインではなく厳格な上限として扱うことが、クローラーがcaptchaを引き起こすトラフィックパターンへ流れていくのを防ぎます。サイトが成長するとトラフィックも増えることがあるため、数週間ごとに予算を見直してください。前の四半期には穏当だったものが、今は穏当でないかもしれません。

責任あるスクレイピング

次のステップ