※本記事のコードや情報は執筆時点の仕様に基づいています。投資は自己責任であり、必ずデモ環境や少額資金でテストした上で運用してください。
Pythonで株価データの取得や自動売買システムを構築する場合、外部サービスとの通信は避けて通れません。証券会社のAPI、金融データプロバイダー、ニュースフィードなど、あらゆるデータソースとの接続に使われるのがHTTP通信です。
📘 外部参考:Python 公式サイト(ダウンロード) / Python 公式ドキュメント(日本語)
Pythonには標準ライブラリの urllib も用意されていますが、記述が冗長で扱いにくいという欠点があります。そこで事実上の標準として広く使われているのが、サードパーティライブラリのrequests(リクエスツ)です。
📘 外部参考:Requests: HTTP for Humans™(公式ドキュメント)
この記事では、requestsライブラリのインストールから、GET・POSTリクエストの基本構文、JSON形式のレスポンス処理、エラーハンドリング、そして実際のWeb APIを使った実践コードまで、API通信の基礎を体系的に解説します。
requestsライブラリとは
まずはrequestsの位置づけと特徴を正確に把握しておきます。
requestsの概要と特徴
requestsは、PythonでHTTP通信を行うためのサードパーティライブラリです。Kenneth Reitz氏によって開発され、「HTTP for Humans(人間のためのHTTP)」を標語に掲げています。
PyPIにおけるダウンロード数は常にトップクラスであり、Pythonエコシステムにおける最も重要なライブラリの一つです。
requestsを使うメリット
標準ライブラリの urllib と比較した場合のメリットは以下のとおりです。
| 項目 | requests | urllib(標準) |
|---|---|---|
| コードの簡潔さ | 非常にシンプル | 冗長になりやすい |
| JSONの扱い | .json() メソッドで一発変換 |
手動でデコードが必要 |
| セッション管理 | Session オブジェクトで容易 |
自前で実装が必要 |
| SSL証明書の検証 | デフォルトで有効 | 設定が必要 |
| タイムアウト設定 | 引数一つで指定可能 | やや煩雑 |
インストール方法
コマンドプロンプトで以下のコマンドを実行してください。
pip install requests
Python 3.12系以降の環境であれば、数秒でインストールが完了します。インストール確認は以下のコマンドで行えます。
pip show requests
requestsはPythonの標準ライブラリには含まれていません。必ずpipでインストールする必要があります。初回実行時に
ModuleNotFoundErrorが出た場合は、インストール漏れを確認してください。
HTTPリクエストの基本概念
requestsの具体的なコードに入る前に、HTTP通信の基本概念を整理します。
HTTPメソッドの種類と用途
Web APIとの通信では、目的に応じて異なるHTTPメソッドを使い分けます。
| メソッド | 用途 | 具体例 |
|---|---|---|
| GET | データの取得 | 株価情報の取得、ニュース記事の取得 |
| POST | データの送信・作成 | 注文の発注、ログイン認証 |
| PUT | データの更新(全体) | 注文内容の全面変更 |
| PATCH | データの更新(部分) | 注文数量のみ変更 |
| DELETE | データの削除 | 注文のキャンセル |
初学者がまず押さえるべきはGETとPOSTの2つです。データの取得にはGET、データの送信にはPOSTを使用します。
リクエストとレスポンスの構造
HTTP通信は「リクエスト(要求)」と「レスポンス(応答)」の一対で成り立っています。
リクエストの構成要素:
- URL(エンドポイント)
- HTTPメソッド(GET / POST など)
- ヘッダー(認証情報、Content-Typeなど)
- ボディ(POSTリクエスト時のデータ)
レスポンスの構成要素:
- ステータスコード(200、404、500など)
- ヘッダー(Content-Type、レート制限情報など)
- ボディ(JSON、HTML、バイナリデータなど)
ステータスコードの読み方
APIから返されるステータスコードは、リクエストの成否を判断する最も重要な指標です。
- 200番台: 成功(200 OK、201 Created)
- 400番台: クライアントエラー(400 Bad Request、401 Unauthorized、404 Not Found)
- 500番台: サーバーエラー(500 Internal Server Error、503 Service Unavailable)
ステータスコード200が返ってきた場合のみ、レスポンスのデータを処理する設計にしてください。それ以外のコードが返された場合はエラー処理に分岐させるのが基本です。
【コピペOK】GETリクエストの基本構文
ここからは実際のコードを使って解説します。まずは最も基本的なGETリクエストです。
シンプルなGETリクエスト
以下のコードは、無料で利用できるテスト用API「JSONPlaceholder」にGETリクエストを送信し、レスポンスを表示するサンプルです。
import requests
# ==============================
# GETリクエストの基本
# ==============================
def basic_get():
url = "https://jsonplaceholder.typicode.com/posts/1"
response = requests.get(url)
print(f"ステータスコード: {response.status_code}")
print(f"Content-Type : {response.headers['Content-Type']}")
print()
if response.status_code == 200:
data = response.json()
print(f"タイトル: {data['title']}")
print(f"本文 : {data['body'][:50]}...")
else:
print(f"エラーが発生しました: {response.status_code}")
if __name__ == "__main__":
basic_get()
JSONPlaceholder(https://jsonplaceholder.typicode.com/)は、API通信の学習やテスト用に世界中で広く利用されている無料のフェイクAPIサービスです。登録不要で利用できます。
クエリパラメータの指定方法
GETリクエストにパラメータを付与する場合、URLに直接 ?key=value と記述する方法もありますが、requestsでは params 引数を使うのが推奨されます。
import requests
# ==============================
# クエリパラメータ付きGETリクエスト
# ==============================
def get_with_params():
url = "https://jsonplaceholder.typicode.com/posts"
params = {
"userId": 1,
"_limit": 3
}
response = requests.get(url, params=params)
print(f"リクエストURL: {response.url}")
print(f"ステータスコード: {response.status_code}")
print()
if response.status_code == 200:
posts = response.json()
for post in posts:
print(f" ID: {post['id']} | タイトル: {post['title'][:30]}...")
else:
print(f"エラー: {response.status_code}")
if __name__ == "__main__":
get_with_params()
params 引数に辞書を渡すと、requestsが自動的にURLエンコードを行い、?userId=1&_limit=3 のようなクエリ文字列を生成します。
タイムアウトの設定
API通信では、サーバーの応答が返ってこない場合に備えて、必ずタイムアウトを設定してください。
response = requests.get(url, timeout=10)
timeout=10 は「10秒以内に応答がなければ例外を発生させる」という設定です。
タイムアウトを設定しないと、サーバーが無応答の場合にプログラムが永久に停止します。本番運用のコードでは必ず設定してください。
【コピペOK】POSTリクエストの基本構文
データの送信にはPOSTリクエストを使用します。
JSONデータの送信
import requests
import json
# ==============================
# POSTリクエストの基本
# ==============================
def basic_post():
url = "https://jsonplaceholder.typicode.com/posts"
payload = {
"title": "テスト投稿",
"body": "requestsライブラリからのPOST送信テストです。",
"userId": 1
}
headers = {
"Content-Type": "application/json; charset=UTF-8"
}
response = requests.post(url, json=payload, headers=headers, timeout=10)
print(f"ステータスコード: {response.status_code}")
print()
if response.status_code == 201:
result = response.json()
print("=== 送信結果 ===")
print(f" ID : {result['id']}")
print(f" タイトル: {result['title']}")
print(f" 本文 : {result['body']}")
else:
print(f"エラー: {response.status_code}")
if __name__ == "__main__":
basic_post()
json=payload と指定することで、requestsが自動的にPythonの辞書をJSON文字列に変換し、適切なヘッダーを付与して送信します。
POSTリクエストの注意点
POSTリクエストを使う場面では、以下の点に注意してください。
- 認証が必要な場合が多い: APIキーやトークンをヘッダーに含める必要がある
- 冪等性がない: 同じリクエストを複数回送信すると、データが重複作成される可能性がある
- テスト環境で十分に検証する: 特に発注系APIでは、本番環境での誤発注を防ぐためにデモ環境でテストする
【コピペOK】実践:公開APIから金融データを取得する
学習用のフェイクAPIではなく、実際の金融データを返す公開APIを使った実践コードを紹介します。
為替レートの取得(Exchange Rate API)
以下のコードは、無料で利用可能なExchange Rate API(https://open.er-api.com/)を使用して、最新の為替レートを取得します。登録不要・無料で利用できるAPIです。
import requests
# ==============================
# 為替レート取得スクリプト
# ==============================
BASE_CURRENCY = "USD"
TARGET_CURRENCIES = ["JPY", "EUR", "GBP", "AUD", "CNY"]
def fetch_exchange_rates():
url = f"https://open.er-api.com/v6/latest/{BASE_CURRENCY}"
print(f"=== {BASE_CURRENCY}基準の為替レート取得 ===n")
try:
response = requests.get(url, timeout=10)
response.raise_for_status()
except requests.exceptions.Timeout:
print("エラー: リクエストがタイムアウトしました。")
return
except requests.exceptions.HTTPError as e:
print(f"エラー: HTTPエラーが発生しました ({e})")
return
except requests.exceptions.ConnectionError:
print("エラー: ネットワーク接続に失敗しました。")
return
data = response.json()
if data.get("result") != "success":
print("APIからのレスポンスが異常です。")
return
rates = data["rates"]
print(f"{'通貨':<6} {'レート':>12}")
print("-" * 20)
for currency in TARGET_CURRENCIES:
if currency in rates:
print(f"{currency:<6} {rates[currency]:>12.4f}")
else:
print(f"{currency:<6} {'N/A':>12}")
print(f"n最終更新: {data.get('time_last_update_utc', '不明')}")
if __name__ == "__main__":
fetch_exchange_rates()
このスクリプトを実行すると、USD(米ドル)を基準とした主要通貨の為替レートが一覧表示されます。
エラーハンドリングの解説
上記コードで使用しているエラーハンドリングのパターンを整理します。
| 例外クラス | 発生条件 | 対処 |
|---|---|---|
requests.exceptions.Timeout |
指定時間内に応答がない | リトライまたは中止 |
requests.exceptions.HTTPError |
4xx・5xxステータスコード(raise_for_status() 使用時) |
エラー内容をログ出力 |
requests.exceptions.ConnectionError |
DNS解決失敗・ネットワーク切断 | 接続確認を促す |
requests.exceptions.RequestException |
上記すべてを包含する基底クラス | 汎用的なエラーキャッチ |
response.raise_for_status() を呼び出すと、ステータスコードが4xx・5xxの場合に自動的に HTTPError 例外が発生します。
本番コードでは必ずtry-exceptでエラーハンドリングを実装してください。ネットワーク通信は常に失敗する可能性があります。
APIキーを使った認証付きリクエスト
多くの本格的なAPIでは、アクセスにAPIキーが必要です。
ヘッダーにAPIキーを含める方法
APIキーの指定方法はサービスによって異なりますが、最も一般的なのはHTTPヘッダーに含める方式です。
import requests
# ==============================
# 認証付きリクエストの基本構文
# ==============================
API_KEY = "your_api_key_here"
headers = {
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json"
}
response = requests.get(
"https://api.example.com/v1/data",
headers=headers,
timeout=10
)
APIキーの管理に関する注意事項
APIキーの取り扱いには十分な注意が必要です。
- コードに直接記述しない: 環境変数や
.envファイルで管理する - GitHubにアップロードしない:
.gitignoreに設定ファイルを追加する - 定期的にローテーションする: 漏洩時のリスクを最小化する
環境変数からAPIキーを読み込む基本パターンは以下のとおりです。
import os
API_KEY = os.environ.get("MY_API_KEY")
if not API_KEY:
print("エラー: 環境変数 MY_API_KEY が設定されていません。")
APIキーをソースコードにハードコーディングすると、GitHubへの誤アップロード時に第三者に悪用されるリスクがあります。環境変数での管理を徹底してください。
Sessionオブジェクトによる効率化
同じAPIに対して複数回リクエストを送る場合、Session オブジェクトを使うと通信効率が向上します。
Sessionの基本的な使い方
import requests
# ==============================
# Sessionによる効率的な通信
# ==============================
def fetch_multiple_posts():
session = requests.Session()
session.headers.update({
"Accept": "application/json"
})
base_url = "https://jsonplaceholder.typicode.com/posts"
print("=== 複数記事の一括取得 ===n")
for post_id in range(1, 4):
response = session.get(f"{base_url}/{post_id}", timeout=10)
if response.status_code == 200:
data = response.json()
print(f"ID: {data['id']} | {data['title'][:40]}...")
else:
print(f"ID: {post_id} | 取得失敗 ({response.status_code})")
session.close()
print("n=== 取得完了 ===")
if __name__ == "__main__":
fetch_multiple_posts()
Sessionオブジェクトを使うと、TCP接続の再利用(Keep-Alive)が自動的に行われるため、複数リクエストの総通信時間が短縮されます。
よくあるエラーと対処法
「ConnectionError: Max retries exceeded」が発生する
URLの綴り間違い、またはサーバーがダウンしている場合に発生します。以下の順番で確認してください。
- URLが正しいかブラウザで直接アクセスして確認する
- インターネット接続が有効か確認する
- 企業プロキシ環境の場合、プロキシ設定が必要な場合がある
プロキシを指定する場合は以下のように記述します。
proxies = {
"http": "http://proxy.example.com:8080",
"https": "http://proxy.example.com:8080"
}
response = requests.get(url, proxies=proxies, timeout=10)
レスポンスが文字化けする
日本語を含むレスポンスが文字化けする場合は、エンコーディングを明示的に指定してください。
response.encoding = "utf-8"
print(response.text)
requestsはレスポンスヘッダーの Content-Type からエンコーディングを推測しますが、ヘッダーの指定が不正確なAPIでは文字化けが発生します。
APIのレート制限(Rate Limit)に引っかかる
多くのAPIには、一定時間あたりのリクエスト回数制限が設けられています。制限を超えると 429 Too Many Requests が返されます。
対処法は、リクエスト間に待機時間を挟むことです。
import time
for i in range(10):
response = requests.get(url, timeout=10)
time.sleep(1) # 1秒間隔を空ける
まとめ
requestsライブラリを使ったAPI通信の基本は、以下のポイントに集約されます。
- GETはデータの取得、POSTはデータの送信に使用する
response.json()でレスポンスをPythonの辞書に変換できるtimeout引数は必ず設定する(未設定はプログラム停止のリスク)- ステータスコードのチェックと
try-exceptによるエラーハンドリングは必須 - APIキーはソースコードに直接書かず、環境変数で管理する
- 複数リクエストには
Sessionオブジェクトを活用する
requestsの基本構文は、将来的に証券API・金融データAPI・ニュースAPIなど、あらゆるWebサービスとの連携に直結するスキルです。この記事で紹介したパターンを確実に身につけ、次のステップであるyfinanceを使った株価データ取得や、各種APIとの実践的な連携に進んでください。
📘 外部参考:yfinance 公式GitHubリポジトリ(README・最新版) / PyPIページ
次のデータを入力してください。

