閉じる

【Python】requestsでWebページのHTMLを取得する方法と注意点

PythonでWebページのHTMLを取得する最初の一歩として、requestsは最有力候補です。

インストールが簡単で、短いコードでGETリクエストを送り、ステータスコードやエンコーディングを確認しながら安全に扱えます。

本記事では、初心者でも迷わないように、最短コードからエラー対策までを丁寧に解説します。

requestsの準備

pipでrequestsをインストール

requestsは標準ライブラリではありません。

まずはpipでインストールします。

プロジェクトごとに仮想環境を作るのが理想ですが、ここではシンプルにインストール手順を示します。

可能であればpython -m pip形式での実行をおすすめします。

Pythonの実体に紐づいたpipが使えるため、バージョンの取り違いを防ぎやすいからです。

Shell
# Windowsの場合
py -m venv .venv              # 任意(仮想環境を作る場合)
.venv\Scripts\activate        # 任意(仮想環境を有効化)
py -m pip install -U requests # requestsをインストール/更新

# macOS / Linuxの場合
python3 -m venv .venv             # 任意(仮想環境を作る場合)
source .venv/bin/activate         # 任意(仮想環境を有効化)
python3 -m pip install -U requests

インストール時には多くのログが表示されます。

以下は一例です。

実行結果
Collecting requests
  Downloading requests-2.32.3-py3-none-any.whl ...
Collecting charset-normalizer<4,>=2 (from requests)
...
Successfully installed certifi-2024.x.x charset-normalizer-3.x.x idna-3.x requests-2.32.3 urllib3-2.x

importで動作確認

インストール後に必ずimportできるかを確認します。

バージョンも一緒に表示しておくと、環境メモとして便利です。

Python
# importできるか確認し、バージョンと簡単なメッセージを出力します
import requests

print(requests.__version__)      # requestsのバージョン確認
print("requests is ready!")      # シンプルな動作確認
実行結果
2.32.3
requests is ready!

requestsでHTMLを取得する方法

最短のGETコード例

まずは最短コードでHTMLを取得してみます。

学習用に安定して応答するhttps://example.comを使います。

Python
# 最短でHTMLを取得して先頭だけ表示する例
import requests

url = "https://example.com"  # 学習用のサンプルサイト
res = requests.get(url)      # GETリクエストを送信

# 取得したHTMLの先頭200文字だけ表示(全文は長いので一部に限定)
print(res.text[:200])
実行結果
<!doctype html>
<html>
<head>
    <title>Example Domain</title>
    ...

ここまでのコードは「成功した場合」を想定しています

実戦では、後述のステータスコード確認とエラー処理を合わせて書くのが基本です。

ステータスコードを確認

HTTPはステータスコードで成功/失敗や追加の指示を表します。

200番台が成功、300番台はリダイレクト、400番台と500番台はエラーの目安です。

まずは成功の確認を習慣にしましょう。

Python
# ステータスコードと簡易なOK判定を確認します
import requests

url = "https://example.com"
res = requests.get(url)

print("status_code:", res.status_code)  # 例: 200
print("ok:", res.ok)                    # Trueなら成功(200〜399あたりが目安)
print("reason:", res.reason)            # 例: OK
実行結果
status_code: 200
ok: True
reason: OK

参考として、よく見るコードの意味を表にまとめます。

範囲意味の目安
200–299成功200(OK), 204(No Content)
300–399リダイレクト301(Moved Permanently), 302(Found)
400–499クライアントエラー400(Bad Request), 404(Not Found)
500–599サーバーエラー500(Internal Server Error), 503(Service Unavailable)

文字化け対策

日本語ページなどでは文字化けが起きることがあります。

requestsはレスポンスヘッダーや内容からエンコーディングを推測しますが、うまくいかない場合はapparent_encodingを使った補正が有効です。

Python
# エンコーディングを確認・補正してからテキスト化する例
import requests

url = "https://www.example.com"  # 実際には日本語サイトで試すと違いが分かりやすいです
res = requests.get(url)

print("encoding(before):", res.encoding)  # サーバーから推定されたエンコーディング
# 必要に応じて補正(誤検出の可能性もあるため、条件付きで設定するのがおすすめ)
if not res.encoding or res.encoding.lower() in ("iso-8859-1", "ascii"):
    res.encoding = res.apparent_encoding

print("encoding(after):", res.encoding)
print(res.text[:200])  # 補正後のテキストの先頭を確認
実行結果
encoding(before): ISO-8859-1
encoding(after): utf-8
<!doctype html>...

補足

常にapparent_encodingが正しいとは限りません

まずはサーバーが返すContent-Typeヘッダーのcharsetを尊重し、怪しい場合だけ補正する方針が実務的です。

よく使うオプションと使い方

timeoutを設定する

timeoutは必ず設定しましょう

未指定だと待ち続ける可能性があります。

接続と読み取りで別々に指定できます。

Python
# 接続(3.05秒)・読み取り(10秒)のタイムアウトを設定する例
import requests

url = "https://httpbin.org/delay/2"  # 2秒遅延して返答するテストAPI
try:
    res = requests.get(url, timeout=(3.05, 10))  # (connect, read)
    print("OK:", res.status_code)
except requests.exceptions.Timeout:
    print("Timeout!")
実行結果
OK: 200

使い分けの目安

  • 1つの数値timeout=10は接続と読み取りの両方に適用されます。
  • タプル(connect, read)で分けると、ネットワーク事情に合わせた調整が可能です。

ヘッダー(User-Agent)を付ける

一部サイトはデフォルトのUser-Agentだとブロックすることがあります。

適切なUser-Agentを明示しましょう。

Python
# 一般的なブラウザ風のUser-Agentを付ける例
import requests

url = "https://httpbin.org/headers"
headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
                  "AppleWebKit/537.36 (KHTML, like Gecko) "
                  "Chrome/122.0.0.0 Safari/537.36"
}
res = requests.get(url, headers=headers, timeout=10)

# サーバーが受け取ったヘッダーを確認(学習用API)
print(res.json()["headers"]["User-Agent"])
実行結果
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36

注意

身元を偽る意図でのUser-Agent偽装は避け、アクセス先のポリシーに従ってください。

クエリパラメータ(params)を付ける

検索条件などをURLのクエリとして付与するにはparams引数が便利です。

辞書を渡すだけでURLに自動で付与されます。

Python
# ?key=value形式のパラメータを付ける例
import requests

url = "https://httpbin.org/get"
params = {
    "q": "python requests",
    "page": 1
}
res = requests.get(url, params=params, timeout=10)

print("Final URL:", res.url)            # エンコード後の最終URLを確認
print("args:", res.json()["args"])      # サーバー側で受け取られたクエリ
実行結果
Final URL: https://httpbin.org/get?q=python+requests&page=1
args: {'page': '1', 'q': 'python requests'}

リダイレクトを制御

requestsはデフォルトでリダイレクトを自動追従します。

挙動を変えたい場合はallow_redirectshistoryを活用します。

Python
# リダイレクトを追う/追わないを比較する例
import requests

url = "https://httpbin.org/redirect/1"

# 追従する(デフォルト)
res1 = requests.get(url, timeout=10)
print("follow: status", res1.status_code)
print("follow: history length", len(res1.history))  # どれだけリダイレクトしたか

# 追従しない
res2 = requests.get(url, allow_redirects=False, timeout=10)
print("no follow: status", res2.status_code)
print("no follow: Location", res2.headers.get("Location"))  # 次のURLが分かる
実行結果
follow: status 200
follow: history length 1
no follow: status 302
no follow: Location https://httpbin.org/get

エラー対策と注意点

HTTPエラーを検出

HTTPエラーはraise_for_status()で検出するのが定番です。

成功時は何も起きず、4xx/5xx時に例外が送出されます。

Python
# HTTPステータスがエラーのときに例外を起こす例
import requests

url = "https://httpbin.org/status/404"  # 404を返すテストURL
res = requests.get(url, timeout=10)

try:
    res.raise_for_status()  # 4xx/5xxの場合にHTTPErrorを投げる
    print("Success:", res.status_code)
except requests.exceptions.HTTPError as e:
    print("HTTPError:", e)
実行結果
HTTPError: 404 Client Error: NOT FOUND for url: https://httpbin.org/status/404

例外をキャッチ

ネットワーク通信ではさまざまな例外が起こり得ます。

基本はRequestExceptionで包括しつつ、よくあるものは個別に捕捉すると原因切り分けがしやすくなります。

Python
# 例外を適切に捕捉して原因をログに出すテンプレート
import requests

url = "https://httpbin.org/delay/5"  # 5秒遅延
try:
    res = requests.get(url, timeout=(2, 2))  # あえて短いtimeoutでエラーに
    res.raise_for_status()                   # HTTPエラー検出
    print("OK:", res.status_code)
except requests.exceptions.Timeout:
    print("Timeout(接続または読み取りが時間切れ)")
except requests.exceptions.ConnectionError:
    print("ConnectionError(名前解決/接続が失敗)")
except requests.exceptions.HTTPError as e:
    print("HTTPError:", e)
except requests.exceptions.TooManyRedirects:
    print("TooManyRedirects(リダイレクトが多すぎ)")
except requests.exceptions.RequestException as e:
    # 上記以外のrequests系例外の最終受け皿
    print("RequestException:", e)
実行結果
Timeout(接続または読み取りが時間切れ)

参考として、代表的な例外の概要をまとめます。

例外名起こりやすい状況
Timeoutサーバーの応答が遅い、timeoutが短すぎる
ConnectionErrorDNS失敗、サーバーダウン、ネットワーク断
HTTPError4xx/5xxステータスが返ってきた
TooManyRedirects無限リダイレクトや回数制限超過
RequestExceptionrequests全般の基底例外(最後に捕捉)

レスポンス内容を確認

HTMLを扱う前に本当にHTMLなのかを確認すると安全です。

ヘッダーのContent-Typeを見たり、サイズや先頭文字列を確認します。

必要に応じてファイル保存も行います。

Python
# レスポンスの内容タイプとサイズ、先頭を確認し、HTMLなら保存する例
import requests
from pathlib import Path

url = "https://example.com"
res = requests.get(url, timeout=10)

content_type = res.headers.get("Content-Type", "")
print("Content-Type:", content_type)
print("Length(bytes):", len(res.content))
print("Head(100):", res.text[:100].replace("\n", " "))

# HTMLらしければ保存
if "text/html" in content_type.lower():
    # エンコーディングを必要に応じて補正
    if not res.encoding or res.encoding.lower() in ("iso-8859-1", "ascii"):
        res.encoding = res.apparent_encoding

    out = Path("page.html")
    out.write_text(res.text, encoding=res.encoding or "utf-8")
    print(f"Saved to {out.resolve()}")
else:
    print("HTMLではない可能性があります。処理を見直してください。")
実行結果
Content-Type: text/html; charset=UTF-8
Length(bytes): 1256
Head(100): <!doctype html> <html> <head>     <title>Example Domain</title> ...
Saved to /your/project/path/page.html

実務での小さなコツ

文字数やサイズが極端に小さいときはエラーページの可能性があります。HTML内のキーワードから異常検知することもあります。

アクセス先の利用規約やrobots.txt、アクセス間隔などのマナーを順守してください。本記事では詳細を扱いませんが、実運用前に必ず確認しましょう。

まとめ

本記事では、requestsでWebページのHTMLを取得する基本を、インストールから最短コード、ステータス確認、文字化け対策、よく使うオプション、そしてエラー処理まで順を追って解説しました。

実務ではtimeoutの設定raise_for_statusによるエラー検出、そしてエンコーディングの確認が特に重要です。

まずは学習用の安定したURLで動作を確かめ、徐々にヘッダーやパラメータ、リダイレクト制御などを組み合わせて、自身の目的に合う堅牢な取得処理へと育てていきましょう。

次のステップとしては、取得したHTMLから情報を抽出するためのライブラリ(Beautiful Soup)も学ぶと、Webスクレイピングの幅が大きく広がります。

この記事を書いた人
エーテリア編集部
エーテリア編集部

人気のPythonを初めて学ぶ方向けに、文法の基本から小さな自動化まで、実際に手を動かして理解できる記事を書いています。

クラウドSSLサイトシールは安心の証です。

URLをコピーしました!