とほほのPython入門 - requests

目次

requestsとは

インストール

pip コマンドでインストールします。

pip install requests

ドキュメント

requests に関するドキュメントは下記にあります。

リクエスト

GETメソッド(requests.get())

GET メソッドを発行するには requests.get() を使用します。

import requests

response = requests.get("https://example.com")
print(response.status_code)
print(response.text)

GETパラメーター(params)

GET パラメーターを指定するには params を指定します。メタ文字が含まれる場合は適切に URL エンコードされます。

params = { "foo": "FOO", "baa": "BAA" }
response = requests.get("https://example.com", params=params)
print(response.status_code)
print(response.text)

POST メソッド(requests.post())

POST メソッドを発行するには requests.post() を使用します。

import requests

response = requests.post("https://example.com")
print(response.status_code)
print(response.text)

POSTパラメーター(data)

POST パラメーターを URL エンコード形式で発行するには data を指定します。メタ文字が含まれる場合は適切に URL エンコードされます。Content-Type は自動的に application/x-www-form-urlencoded となります。

data = { "foo": "FOO", "baa": "BAA" }
response = requests.post("https://example.com", data=data)

POSTパラメーター(json)

POST パラメーターを JSON 形式で発行するには json を指定します。Content-Type は自動的に application/json となります。

data = { "foo": "FOO", "baa": "BAA" }
response = requests.post("https://example.com", json=data)

PUT メソッド(requests.put())

PUT メソッドを発行するには requests.put() を使用します。

data = { "foo": "FOO", "baa": "BAA" }
response = requests.put("https://example.com", json=data)

PATCH メソッド(requests.patch())

PATCH メソッドを発行するには requests.patch() を使用します。

data = { "foo": "FOO", "baa": "BAA" }
response = requests.patch("https://example.com", json=data)

DELETE メソッド(requests.delete())

DELETE メソッドを発行するには requests.delete() を使用します。

response = requests.delete("https://example.com/users/123")

HEAD メソッド(requests.head())

HEAD メソッドを発行するには requests.head() を使用します。

response = requests.head("https://example.com")

OPTIONS メソッド(requests.options())

OPTIONS メソッドを発行するには requests.options() を使用します。

response = requests.options("https://example.com")
print(response.headers.get("Allow"))

汎用メソッド(requests.request())

requests.request() を使用するとメソッドを引数で指定することができます。

response = requests.request("GET", "https://example.com")

タイムアウト時間(timeout)

タイムアウト時間を指定するには timeout に秒数を指定します。指定しない場合は無限待ちとなるため、プログラムのブロッキングを防ぐために timeout を必ず指定することが推奨されています。

response = requests.post("https://example.com", timeout=30)

リクエストヘッダ(headers)

HTTP ヘッダを送信するには headers パラメーターを指定します。

headers = {
    "User-Agent": "MyAgent/1.0",
    "Authorization": "Bearer ACCESS_TOKEN",
}
response = requests.post("https://example.com", headers=headers)

リクエストCookie(cookies)

Cookie を送信するには cookies パラメーターを指定します。

cookies = {
    "session-id": "..."
}
response = requests.post("https://example.com", cookies=cookies)

プロキシサーバー(proxies)

プロキシサーバーは proxies パラメーターで指定します。環境変数 HTTP_PROXYHTTPS_PROXY で指定することもできます。

proxies = {
    "http":  "http://proxy.example.com:8080",
    "https": "http://proxy.example.com:8080",
}
response = requests.get("https://example.com", proxies=proxies)

BASIC認証(auth)

BASIC 認証を用いるには auth パラメーターを指定します。

response = requests.get("https://example.com", auth=(user, password))

証明書検証の無効化(verify)

試験環境などで SSL 証明書の検証を無効化するには verify パラメーターに False を指定します。

response = requests.get("https://example.com", verify=False)

ただし、上記だけだと通信には成功しますが、下記の様な警告メッセージが表示されます。

/usr/local/lib/python3.12/site-packages/urllib3/connectionpool.py:1097:
InsecureRequestWarning:
Unverified HTTPS request is being made to host 'localhost.com'.
Adding certificate verification is strongly advised.
See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#tls-warnings

警告メッセージも抑止するには下記を追加してください。

from requests.packages.urllib3.exceptions import InsecureRequestWarning
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)

本番環境では必ず証明書検証を行うようにしてください。

ファイルアップロード(files)

フォーム形式でファイルアップロードするには下記の様にします。file1file2<input type="file" name="file1">name 属性に相当します。

with open("example1.jpg", "rb") as f:
    data1 = f.read()
with open("example2.jpg", "rb") as f:
    data2 = f.read()
files = [
    ("file1", ("example1.jpg", data1, "image/jpeg")),
    ("file2", ("example2.jpg", data2, "image/jpeg")),
]
response = requests.post("http://localhost/upload", files=files)

巨大なファイルをアップロードする際は下記のようにも記述できます

with open("example1.zip", "rb") as f1, \
     open("example2.zip", "rb") as f2:
    files = [
        ("file1", ("example1.zip", f1, "image/jpeg")),
        ("file2", ("example2.zip", f2, "image/jpeg")),
    ]
    response = requests.post("http://localhost/upload", files=files)

image/jpeg などのファイルのコンテンツタイプが不明な場合は mimetypes.guess_type() で推測し、推測できない場合は application/octet-stream を指定するとよさそうです。

import mimetypes
ctype, _ = mimetypes.guess_type(filename)
ctype = ctype or 'application/octet-stream'
files = [ ("file", (filename, f, ctype)) ]

ファイルダウンロード(stream)

巨大なファイルをダウンロードするには streamTrue を指定し、iter_content() で一定サイズ毎に読み取ります。安全のために r.raise_for_status() を指定してください。

with requests.get("https://example.com/bigfile.zip", stream=True) as r:
    r.raise_for_status()
    with open("bigfile.zip", "wb") as f:
        for chunk in r.iter_content(chunk_size=1024*1024):
            if chunk:
                f.write(chunk)

リダイレクト対応(allow_redirects)

requests は通常サーバーから 3xx のステータスが返却されると自動的にリダイレクトしますが、allow_redirectsFalse を指定すると自動リダイレクトを抑止することができます。

response = requests.get("http://localhost", allow_redirects=False)

クライアント証明書(cert)

cert にクライアント証明書を指定することができます。証明書と秘密鍵を含む単一のファイル(*.pem)を指定するか、証明書ファイル(*.crt) と秘密鍵ファイル(*.key) を個別に指定することができます。

response = requests.get("http://localhost", cert="client.pem")
response = requests.get("http://localhost", cert=("client.crt", "client.key"))

レスポンス

requests.get() などの戻り値である Response クラスのオブジェクトは下記などの情報を含みます。

HTTPステータスコード(response.status_code)

status_code は HTTP ステータスコードを返します。2xx は成功、3xx はリダイレクト、4xx はクライアント原因エラー、5xx はサーバー原因エラーです。

response = requests.get("https://example.com")
print(response.status_code)        # 200

HTTPステータス理由(response.reason)

reasonForbiddenNot Found などのHTTP ステータスコードの理由を返します。

response = requests.get("https://example.com/path")
print(response.reason)        # Not Found など

レスポンスコンテンツ(response.content)

content はレスポンスの内容をバイナリ形式で参照します。

response = requests.get("https://example.com")
print(response.content)

レスポンステキスト(response.text)

text はレスポンスの内容をテキスト形式で参照します。

response = requests.get("https://example.com")
print(response.text)
print(response.encoding)        # utf-8 など

レスポンスJSON(response.json())

json() はレスポンスの内容を JSON として参照します。JSON でない場合は JSONDecodeError 例外が発生します。

response = requests.post("https://example.com")
print(response.json())

レスポンスヘッダ(response.headers)

headers はレスポンスヘッダを返します。

response = requests.get("https://example.com")
print(response.headers["Content-Type"])
for key, value in response.headers.items():
    print(f"{key}: {value}")

レスポンスCookie(response.cookies)

cookies はレスポンスの Cookie 情報を返します。

response = requests.get("https://example.com")
print(response.cookies["SessionID"])
for key, value in response.cookies.items():
    print(f"{key}: {value}")

経過時間(response.elapsed)

elapsed はリクエスト・レスポンスに要した時間を timedelta 型で返します。

response = requests.get("https://example.com")
print(response.elapsed)

その他

セッション

requests.Session() を用いると、指定したヘッダ情報や、サーバーから返却された Cookie 情報を保持するセッションを生成してリクエストすることができます。

session = requests.Session()
session.headers.update({"User-Agent": "MyAgent"})
data = { "user_name": "yamada", "password": "********" }
response = session.post("https://example.com/login", data=data)   # Cookieを受け取る
response = session.get("https://example.com/dashboard")           # Cookieを送信する
session.close()

エラー処理

requests は下記の例外を発行します。HTTPErrorraise_for_status() を呼び出して 4xx や 5xx エラーが発生した場合のみ発生し、e.response でレスポンスの詳細を得ることができます。

try:
    response = requests.get("https://example.com")
    response.raise_for_status()
except requests.ConnectTimeout:        # 接続タイムアウト
    print("ConnectTimeout")
except requests.ReadTimeout:           # 読み込みタイムアウト
    print("ReadTimeout")
except requests.Timeout:               # 上記以外のタイムアウト
    print("Timeout")
except requests.ConnectionError:       # 上記以外の接続エラー
    print("ConnectionError")
except requests.HTTPError as e:        # HTTPステータスエラー
    print(f"HTTPError({e.response.status_code})")
except requests.TooManyRedirects:      # リダイレクト回数超過
    print("TooManyRedirects")
except requests.JSONDecodeError:       # JSONデコードエラー
    print("JSONDecodeError")
except requests.RequestException:      # その他エラー(上記例外の基底クラス)
    print("RequestException")

デバッグ

下記の行を追加することで requests 内部の詳細デバッグを出力することができます。

import http.client as http_client
http_client.HTTPConnection.debuglevel = 1