お悩み女子Pythonでサイトの情報を集めたいけれど、規約とかrobots.txtとか、どこまで確認すればいいのか分からなくて手が止まる……
スクレイピングは、Webページの内容をプログラムで自動的に取り出して、表やCSVにまとめる方法です。毎週ブラウザからコピーしている価格やお知らせの更新を、Pythonで減らせます。ただし、コードを書く前に確認しておくことが3つあります。
この記事では、スクレイピング前に確認する規約・robots.txt・アクセス間隔の3点を順番に紹介します。Python標準のライブラリだけで動くコードを載せていて、Windows 11 と Python 3.12 で動くことを確かめています。
- スクレイピング前に確認する3つのことと、見る順番
- 利用規約で自動取得の記載を探す方法
- robots.txt の読み方と、Pythonでの確かめ方
- 待機時間の入れ方と、取得を止める合図
スクレイピングの事前確認|見る3つのことと順番
スクレイピングでは、「取れるか」より先に「取ってよいか」と「相手に負担をかけないか」を確かめます。次の3つを、規約、robots.txt、アクセス負荷の順に見ると手戻りが少なくなります。
| 確認すること | 見る場所 | 分かること |
|---|---|---|
| 1. 利用規約 | サイトのフッターにある利用規約のページ | 自動での取得やデータの利用が禁じられていないか |
| 2. robots.txt | サイトのトップ直下(https://サイト名/robots.txt) | 取得を控えてほしいページと、待ってほしい秒数 |
| 3. アクセス負荷 | 自分のコード(待機時間・件数・エラー時の動き) | 相手のサーバーに短時間で負担をかけないか |
規約で自動取得が禁じられていれば、robots.txt に何も書かれていなくても先へ進めません。そのため規約が最初です。
なべくんコードを書く前に、公式のデータ提供(APIやCSVのダウンロード)がないか、手作業で足りないかも考えます。この順で考えるのが、勝率の高い選び方です。
スクレイピングの利用規約|禁止の書き方と確認の記録
規約で見るのは、自動取得に触れた記載の有無と、取得したデータの使い道です。
規約ページの探し方
サイトのフッター(ページの最下部)にある「利用規約」「ご利用条件」「サイトポリシー」などのリンクを探します。サービスごとに規約が分かれているサイトでは、取得したいページが属するサービスの規約を読みます。
自動取得の記載の読み方
書き方はサイトごとに違います。次は、イメージをつかむための架空の条文です。
ロボット、スパイダー、スクレイパーその他の自動的な手段で、本サイトの情報を収集してはならない。
- 自動取得を禁じる記載がある:取得しません。必要なら運営者に問い合わせて許可を得ます。
- 記載がない:禁止されていないだけで、許可されたわけではありません。次の確認に進みます。
データの使い道と記録
取得できるかとは別に、取ったデータを何に使うかも確認します。社内の集計だけなのか、文章や画像を自社サイトに載せたり社外に配ったりするのかで、確認する内容が変わります。個人情報が含まれるページは、集める必要があるかを先に考えます。
筆者は法律の専門家ではないため、著作権や個人情報の可否は判断しません。社外に出すデータは、著作権法などの条文を確認し、社内の法務担当や専門家に相談してください。
規約を読んだら、確認した日・規約ページのURL・自動取得の記載の有無をメモに残します。項目は、後半の確認メモの表にまとめています。
スクレイピングとrobots.txt|読み方と主な4つの記述
robots.txt は、サイトの運営者が巡回プログラムに向けて「ここは取得しないでほしい」と伝えるテキストファイルです。ブラウザで開けば、誰でも中身を読めます。
場所と中身の例
https://サイト名/robots.txt をブラウザのアドレス欄に入力すると読めます。ファイルがないサイトでは、404(見つかりません)と表示されます。中身の例は次のとおりです(架空のサイトです)。
User-agent: *
Disallow: /admin/
Crawl-delay: 5
すべてのプログラム(*)に、/admin/ で始まるページの取得を控えることと、5秒の間隔を空けることを求めています。
主な記述と、許可証ではない点
| 記述 | 意味 |
|---|---|
| User-agent | どの巡回プログラムへの指定か(* はすべて) |
| Disallow | 取得を控えてほしいパス(その文字で始まるページ) |
| Allow | Disallow の中で、例外として取得してよいパス |
| Crawl-delay | 次のアクセスまで待ってほしい秒数 |
Crawl-delay は標準仕様(RFC 9309)に載っていない記述で、書かれていないサイトもあります。書かれていたら、その秒数以上の間隔を空けて取得します。
もう1つ押さえたいのは、robots.txt が許可証ではないことです。RFC 9309 には、これらの規則はアクセスを許可する仕組みではない(These rules are not a form of access authorization)と書かれています。Allow や記載なしでも、規約で自動取得が禁じられていれば取得してよいことにはなりません。規約と robots.txt は、別々に確認します。
スクレイピングのrobots.txt確認|Pythonのurllib.robotparserで調べる
Python 標準ライブラリの urllib.robotparser を使うと、取得したいURLが robots.txt で許されているかを True か False で調べられます。追加のインストールは要りません。
文字列で動きを確かめる
まず、前の節の robots.txt を文字列で渡して動きを見ます。ネットワークにつなぐ必要はありません。
from urllib.robotparser import RobotFileParser
robots_txt = """\
User-agent: *
Disallow: /admin/
Crawl-delay: 5
"""
rp = RobotFileParser()
rp.parse(robots_txt.splitlines())
bot = "MyResearchBot"
print(rp.can_fetch(bot, "https://example.com/"))
print(rp.can_fetch(bot, "https://example.com/admin/users"))
print(rp.crawl_delay(bot))
実行結果は次のとおりです。上から順に、トップページの取得、/admin/ 配下の取得、待ってほしい秒数です。
True
False
5
can_fetch(名前, URL) が、その名前のプログラムが取得してよいかを返します。名前は自分で決めます。robots.txt にその名前の指定がなければ、* の指定が使われます。
実際のサイトのrobots.txtを読む
次は、インターネット上の robots.txt を読む書き方です。read() が、指定したURLの robots.txt を取りに行きます。ここでは、文書の例示用ドメインの example.com を使います。
from urllib.robotparser import RobotFileParser
rp = RobotFileParser()
rp.set_url("https://example.com/robots.txt")
rp.read()
print(rp.can_fetch("MyResearchBot", "https://example.com/"))
print("Crawl-delay:", rp.crawl_delay("MyResearchBot"))
True
Crawl-delay: None
2026年10月18日に確かめた時点では、example.com に robots.txt はなく、404 が返りました。制限の記載がないものとして扱われ、can_fetch は True です。example.com は読む動きの確認だけに使い、ページの取得には使いません。
robots.txtを読めなかったときの動き
robots.txt を取りに行ったときの応答で、can_fetch の結果が変わります。応答を変えられる手元のテスト用サーバーで確かめた結果です(Python 3.12.10)。
| robots.txt の応答 | can_fetch の結果 | 扱われ方 |
|---|---|---|
| 200(正常に読めた) | 書かれた規則のとおり | 記述に従う |
| 404(ファイルがない) | True | 制限の記載なしとして扱う |
| 401・403(拒否された) | False | すべて禁止として扱う |
| 500・503(サーバーの不調) | False | 読めていないので、すべて禁止として扱う |
RFC 9309 では、400番台でファイルが使えないときは「どのページにアクセスしてもよい」(MAY)、500番台で読めないときは「すべて禁止として扱う」(MUST) とされています。Python は 401 と 403 も禁止として扱うので、標準仕様より慎重な動きです。
read() は User-Agent が Python-urllib/3.12 のまま取りに行くため、この User-Agent を弾くサイトでは 403 が返り、実際の robots.txt を読む前にすべて False になります。この動きもテスト用サーバーで確かめました。自分の User-Agent を付けて読む書き方は、次の節の load_robots 関数です。
Allowを書く順番で結果が変わる点
RFC 9309 は「いちばん長く一致した規則を使う」と定めていますが、Python の robotparser は、書かれた順に最初に一致した規則を使います。Disallow: /search の次に Allow: /search/help を書くと、/search/help は False になります。Allow の行を先に書くと True になりました。
スクレイピングの待機時間|アクセス間隔の決め方と取得コード
アクセス負荷で見るのは、短い時間に何回アクセスするかです。for 文で取得をくり返すと、待機を入れない限り、人がブラウザで開くよりずっと速く、立て続けにリクエストを送ってしまいます。
待機時間と件数の決め方
「何秒空ければ安全」という決まりは、標準仕様(RFC 9309)にもありません。次の考え方で決めます。
- Crawl-delay があれば、その秒数以上を空ける
- なければ、1ページ取るごとに数秒待つところから始める
- 並列では動かさず、1ページずつ順番に取る
- 1回の実行で取る件数の上限を決める
数秒という数字は筆者の目安で、測って決めたものではありません。429 などが返ったら、間隔を広げます。
待機つきの取得コード
robots.txt の確認、待機、エラー時の中止を1本にした例です。宛先は、自分のPCの中に立てるテスト用サーバー(127.0.0.1)にしています。まず手元で動きを確かめてから、BASE_URL と PATHS を書き換えます。
準備として、適当なフォルダに次の内容の robots.txt を作ります。あわせて、a.html・b.html・c.html と、private フォルダの中の d.html を置きます(中身は何でも構いません)。
User-agent: *
Disallow: /private/
Crawl-delay: 4
そのフォルダでコマンドプロンプトを開き、テスト用サーバーを起動します。–bind 127.0.0.1 は、自分のPCの中からだけ見えるようにする指定です。止めるときは Ctrl+C を押します。
py -m http.server 8000 --bind 127.0.0.1
別のコマンドプロンプトで、次のコード(polite_fetch.py)を実行します。
import time
import urllib.error
import urllib.request
from urllib.parse import urljoin
from urllib.robotparser import RobotFileParser
BASE_URL = "http://127.0.0.1:8000"
PATHS = ["/a.html", "/private/d.html", "/b.html", "/c.html"]
BOT_NAME = "MyResearchBot"
USER_AGENT = f"{BOT_NAME}/0.1 (contact: you@example.com)"
MIN_WAIT = 2 # 秒。robots.txt の Crawl-delay が大きければそちらを使う
def open_url(url):
req = urllib.request.Request(url, headers={"User-Agent": USER_AGENT})
return urllib.request.urlopen(req, timeout=10)
def load_robots():
"""自分の User-Agent で robots.txt を読む。確認できなければ None"""
rp = RobotFileParser()
try:
with open_url(urljoin(BASE_URL, "/robots.txt")) as res:
rp.parse(res.read().decode("utf-8").splitlines())
except urllib.error.HTTPError as e:
if e.code in (401, 403) or e.code >= 500:
return None
rp.parse([]) # 404 などは「制限の記載なし」として扱う
except urllib.error.URLError:
return None
return rp
rp = load_robots()
if rp is None:
raise SystemExit("robots.txt を確認できないため中止します")
wait = max(MIN_WAIT, rp.crawl_delay(BOT_NAME) or 0)
print(f"待機時間: {wait}秒")
start = time.monotonic()
for path in PATHS:
url = urljoin(BASE_URL, path)
if not rp.can_fetch(BOT_NAME, url):
print(f"スキップ(robots.txtで禁止): {path}")
continue
try:
with open_url(url) as res:
print(f"取得 {res.status}: {path}(開始から{time.monotonic() - start:.1f}秒)")
except urllib.error.HTTPError as e:
print(f"{e.code} が返りました: {path}")
if e.code in (403, 429, 503):
break # 拒否・過多・不調の合図なので、ここで止める
time.sleep(wait)
実行結果は次のとおりです。
待機時間: 4秒
取得 200: /a.html(開始から0.0秒)
スキップ(robots.txtで禁止): /private/d.html
取得 200: /b.html(開始から4.0秒)
取得 200: /c.html(開始から8.0秒)
MIN_WAIT の2秒と Crawl-delay の4秒の大きいほうを使うので、間隔は4秒です。Disallow に当たる /private/d.html は送信せずに飛ばし、テスト用サーバーのログにもリクエストは残っていません。
429 で止まる動きは、429 を返すように作った別のテスト用サーバーで、2ページ目の取得で止まることを確かめています(403・503 も同じ分岐に入ります)。BOT_NAME と USER_AGENT を分けているのは、robots.txt に書かれるのが短い名前で、リクエストには連絡先つきの全文を付けたいためです。詳しくはUser-Agentとは?スクレイピング時に誤解しやすい基本をご覧ください。
取得を止める合図
次の応答が返ったら、いったん取得を止めます。同じ間隔でくり返しても、状況は良くなりません。
- 429(Too Many Requests):短い時間にリクエストが多すぎるという応答です。Retry-After ヘッダーがあれば、その秒数が過ぎるまで待ちます(RFC 6585)。
- 403(Forbidden):サーバーが理解したうえで、実行を拒んでいる応答です(RFC 9110)。拒否をかいくぐる方法は探さず、原因を確かめます。
- 503(Service Unavailable):一時的な過負荷やメンテナンスで処理できない応答です(RFC 9110)。時間を空けてからやり直します。
原因の切り分けは403・429エラーが出たときの確認順で、再試行の間隔の取り方はリトライとバックオフの基本で扱っています。
スクレイピング実行前のチェックリスト|確認メモの表
確認した内容は、実行前に1枚のメモにしておくと、あとから「何を確認したか」を説明できます。Excel やスプレッドシートに、取得するサイトごとに1行ずつ記録します。
確認メモに残す項目
| 項目 | 記録する内容 | 記入例(架空) |
|---|---|---|
| 取得するURL | 対象ページのURL(一覧なら条件も) | https://example.com/list |
| 規約の確認 | 確認した日と、自動取得の記載の有無 | 26年10月18日・記載なし |
| robots.txtの確認 | 確認した日と、can_fetch の結果 | 26年10月18日・True |
| 待機時間と件数 | コードで使う秒数と、1回で取る上限 | 5秒・20件 |
| データの使い道 | 社内の集計か、社外への公開か | 社内の集計のみ |
| 止める合図 | 何が返ったら取得をやめるか | 403・429・503 |
最初の1回は、3件ほどだけ取って、内容とエラーの有無を確かめます。取れたHTMLはファイルに保存しておくと、取り出す処理を直すときに同じページへ何度もアクセスせずに済みます。
スクレイピングの事前確認に関するよくある質問
規約・robots.txt・アクセス間隔について、調べるときによく出てくる疑問をまとめました。
- robots.txt がないサイトは、自由に取得してよいですか?
-
404 が返るのは、取得を控えてほしいページの記載がない状態です。Python の robotparser も True を返します。ただし、規約で自動取得が禁じられていないかは別に確認し、待機時間も同じように入れます。
- 規約に何も書かれていなければ、取得して問題ありませんか?
-
書かれていないことは、許可されたこととは違います。規約が別のページに分かれているサイトもあります。迷うときは、運営者に問い合わせるのがいちばん確実です。社外に出すデータは、法務担当や専門家にも相談してください。
まとめ|スクレイピングは規約・robots.txt・間隔の順に確認する
スクレイピング前の確認を整理します。
利用規約:最初に確認する。自動取得の記載の有無とデータの使い道を見て、確認日を残す。
robots.txt:ブラウザで読み、Python の can_fetch で確かめる。許可証ではないので、規約とは別に確認する。
アクセス間隔:Crawl-delay 以上、なければ数秒から。1ページずつ、件数に上限をつけ、403・429・503 で止める。
初めてのサイトでは、まず3件だけ取って動きを見るのが近道です。うまく動いたら、確認メモを残したうえで件数を増やします。
スクレイピングの次の一歩は、次の記事でも扱っています。
参考資料
urllib.robotparser | Python 3 ドキュメント
RFC 9309 Robots Exclusion Protocol
RFC 6585 Additional HTTP Status Codes
RFC 9110 HTTP Semantics
著作権法 | e-Gov 法令検索
