Pythonの基本文法をひと通り覚えたあと、次にやってみたくなるのがWebからのデータ取得ではないでしょうか。
天気を毎朝記録する。公開されているデータを自動で集める。作ってみたいものが急に増えてくる場所です。
そこで必ず名前が出てくるのがrequestsというライブラリです。Pythonの外部ライブラリの中でも、とりわけよく見かける存在です。
この記事では、requestsで最初に覚えたい使い方を順番に追いかけます。動かせるコードと、実務でつまずきやすい落とし穴もあわせて紹介します。
requestsは何をしてくれるライブラリなのか¶
ひとことで言えば、requestsはPythonからWebサーバーへお願いを出すための道具です。ブラウザでURLを開いてページを受け取る動きを、そのままコードから実行できます。
このやり取りの決まりごとがHTTPです。requestsは、そのHTTPの細かい手続きをまとめて引き受けてくれます。
実は、Pythonには標準ライブラリだけでも同じことができるurllib.requestが入っています。それでもrequestsが選ばれ続けているのは、書く量が段違いに少ないからです。
おもしろいことに、Python公式ドキュメントのurllib.requestのページには、より高水準のHTTPクライアントとしてRequestsパッケージを推奨する、という一文が置かれています。標準ライブラリの説明が外部ライブラリを勧めているわけです。
まずはインストールから始める¶
requestsは標準ライブラリではないので、最初にインストールが必要です。pipコマンドを使います。
pip install requests
インストールで困ったときは、pipそのものの使い方を先に押さえておくと迷いません。【関連記事】Pythonのpipとは?Pythonのライブラリを管理するコマンド
執筆時点の最新版は2.34.2で、2026年5月14日に公開されています。動作にはPython 3.10以降が必要なので、古いバージョンを使っている場合は先に確認しておきましょう。
インストールされるのはrequestsだけではありません。urllib3やcertifiなど、通信と証明書の検証を担当するライブラリも一緒に入ります。
最初の1本をGETで取ってくる¶
準備ができたら、さっそく1本リクエストを送ってみましょう。ページの内容を取ってくる操作はGETと呼ばれます。
次のコードは、テスト用に公開されているサイトへリクエストを送り、結果を表示するものです。
import requests
response = requests.get("https://httpbin.org/get", timeout=10)
print(response.status_code)
print(response.headers["content-type"])
実行すると、次のような2行が表示されます。
200
application/json
最初の200が、うまくいったことを示す番号です。この番号はステータスコードと呼ばれ、通信がどうなったかを教えてくれます。
検索条件を付けたいときは、URLに文字列を足す必要はありません。paramsに辞書を渡せば、requestsが正しい形に組み立ててくれます。
import requests
params = {"q": "python", "page": 2}
response = requests.get("https://httpbin.org/get", params=params, timeout=10)
print(response.url)
表示されるURLは次のようになります。
https://httpbin.org/get?q=python&page=2
記号の付け方を自分で気にしなくていいのは、地味ですがありがたいところです。
返ってきたレスポンスの中身を見る¶
requests.getが返してくるのは、文字列ではなくレスポンスオブジェクトです。この中に、結果のすべてが詰まっています。
よく使うものを表にまとめました。最初はこの5つだけ覚えれば十分です。
| 書き方 | 取り出せるもの | 使う場面 |
|---|---|---|
response.status_code |
ステータスコードの数値 | 成功したかどうかの判定 |
response.text |
本文を文字列にしたもの | HTMLやテキストを読むとき |
response.content |
本文をバイト列のまま | 画像やファイルの保存 |
response.json() |
本文をPythonの辞書やリストへ変換 | Web APIを使うとき |
response.headers |
サーバーが返した付加情報 | 種類や文字コードの確認 |
文字として読むか、JSONとして読むか¶
HTMLページを取ってきたなら、response.textで文字列として読みます。素直な使い方です。
一方でWeb APIを相手にするなら、response.json()の出番になります。返ってきたJSONを、Pythonの辞書やリストへ一発で変換してくれます。
import requests
response = requests.get("https://httpbin.org/json", timeout=10)
data = response.json()
print(type(data))
print(data["slideshow"]["title"])
実行結果は次のとおりです。
<class 'dict'>
Sample Slide Show
辞書になってしまえば、あとはいつものPythonです。JSONそのものの扱いに不安があるなら、こちらもあわせてどうぞ。【関連記事】PythonでJSONデータの扱いをマスター!API連携に必須のjsonモジュールの使い方
なお、JSONではないものにresponse.json()を使うと、JSONDecodeErrorという例外が出ます。中身がJSONかどうかは、headersのcontent-typeで確かめられます。
文字化けしたときに見る場所¶
日本語のページを取ってきたら文字化けした。requestsを使い始めた人が、かなりの確率でぶつかる場面です。
requestsはサーバーの情報から文字コードを推測しますが、その情報が正しくないサイトも存在します。そんなときはresponse.encodingを自分で指定します。
import requests
response = requests.get("https://example.com", timeout=10)
response.encoding = "utf-8"
print(response.text[:100])
私は10年ほどエンジニアとして開発に関わってきましたが、文字化けの調査はいまだに面倒な作業のひとつです。表示がおかしいときは、まずresponse.encodingに何が入っているかを表示してみてください。
エラーをきちんと拾う¶
ここからが、練習と実務の分かれ目になる話です。通信は、失敗することを前提に書く必要があります。
見落としやすいのは、requestsが4xxや5xxを受け取っても例外を出さない点です。ページが見つからなくても、処理は何ごともなかったように次の行へ進みます。
raise_for_statusで異常を表に出す¶
そこで使うのがraise_for_statusです。ステータスコードが4xxや5xxのとき、HTTPErrorという例外を発生させてくれます。
import requests
try:
response = requests.get("https://httpbin.org/status/404", timeout=10)
response.raise_for_status()
except requests.exceptions.HTTPError as e:
print(f"サーバーがエラーを返しました: {e}")
except requests.exceptions.RequestException as e:
print(f"通信そのものに失敗しました: {e}")
else:
print(response.text)
実行すると、404を受け取ったことがはっきり表示されます。
サーバーがエラーを返しました: 404 Client Error: NOT FOUND for url: https://httpbin.org/status/404
失敗を静かに素通りさせないことが、通信処理でいちばん大事な心がけです。あとから原因を追いかけるとき、この1行があるかどうかで調査時間がまるで変わります。
例外の種類を覚えるのが大変なら、RequestExceptionだけ押さえておけば大丈夫です。requestsの通信系の例外は、すべてこれを親に持っています。
エラーメッセージの読み方そのものに不安があるなら、こちらも参考になります。【関連記事】Pythonのエラー文はどこを読めばいい?初心者向けtracebackの見方
timeoutを書き忘れると何が起きるか¶
ここまでのコードで、毎回timeoutを付けてきたことに気づいたでしょうか。あれは飾りではありません。
requestsの公式ドキュメントには、ほぼすべての本番コードでほぼすべてのリクエストにこのパラメータを使うべきだと書かれています。付けなければプログラムが無限に待ち続ける可能性がある、とまで明記されています。
これは大げさな警告ではありません。私も、外部APIを毎晩たたくバッチでtimeoutを書き忘れたことがあります。
相手のサーバーが応答を返さなくなった夜、処理は落ちもせず止まりもせず、ただ待ち続けていました。翌朝までデータが1件も更新されず、原因にたどり着くまでにずいぶん時間を使いました。
timeoutは、書き忘れても普段は何も起きないという点がやっかいです。相手が不調になった日にだけ牙をむきます。
もうひとつ、勘違いしやすい仕様があります。timeoutはダウンロード全体の制限時間ではなく、サーバーが応答を返さない状態が指定秒数続いたときに例外を出すための設定です。
大きなファイルを落とすときに、少し長めの秒数を書いても意味が薄いのはこのためです。まずは10秒あたりを目安に、必ず付ける習慣をつけましょう。
標準ライブラリのurllibとどう違うのか¶
外部ライブラリを増やしたくない場面もあります。そこで、標準ライブラリのurllib.requestとの違いも見ておきましょう。
同じ処理を書き比べると、差がはっきりします。
| 項目 | requests | urllib.request |
|---|---|---|
| インストール | pipで追加が必要 | 標準で入っている |
| JSONの取得 | response.json() の1行 |
読み込んでからjsonで変換 |
| パラメータ付きのURL | params に辞書を渡す |
urlencodeで自分で組み立て |
| 文字コードの処理 | 自動で推測して変換 | 自分でdecodeする |
| エラー処理 | 例外の親クラスが1つに整理 | HTTPErrorとURLErrorを個別に |
学習用のちょっとした処理ならurllib.requestで十分です。ただ、APIを何本もたたくようなコードでは、requestsのほうが読みやすく短くなります。
実際にWeb APIを使う流れを追ってみたい人は、こちらの記事が練習台になります。【関連記事】PythonからOpenAIのAPIを使う方法を解説!
何から練習すればいいか¶
まずは、公開されているテスト用のURLへGETを1本送るところからで構いません。status_codeが200になるのを自分の目で見るのが出発点です。
次に、response.json()で辞書を取り出してみてください。ここまで来れば、世の中の多くのWeb APIは同じ形で扱えます。
そして、コードを書くときは最初からtimeoutとraise_for_statusを並べて書く癖をつけましょう。あとから足すより、最初から入れておくほうがずっと楽です。
requestsは、覚えることが少ないのに長く使い続けられる珍しい道具です。今日の練習が、そのまま実務のコードにつながっていきます。
ここまでお読みいただきありがとうございました。