大規模データセットのページングと収集
ページング、next_cursor パターン、time.sleep によるレート制限、プログレスバーを扱います。
「大規模データセットのページングと収集」はCoddyKit上の無料Learn AI with Pythonレッスンです。 これはレッスン2/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはLearn AI with Python学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Learn AI with Pythonコースには全4レッスンが含まれています。
ページネーションが存在する理由
APIが何百万件ものレコードを1回のレスポンスで返すことは、ほとんどありません。各レスポンスを小さく高速に保つため、結果をページに分割します。
データセット全体を収集するには、すべてのページを順番に処理し、結果を結合する必要があります。このレッスンでは、一般的なページネーションの方式に加えて、レート制限と進捗の追跡について学びます。
ページ番号によるページネーション
最も単純な方式では、pageパラメータを使います。APIが空のページを返すまで、値を1つずつ増やします。
import requests
all_items = []
page = 1
while True:
resp = requests.get(url, params={"page": page, "per_page": 100}, timeout=10)
resp.raise_for_status()
items = resp.json()
if not items:
break
all_items.extend(items)
page += 1
print(len(all_items), "items collected")カーソル/次のURLによるページネーション
多くの最新のAPIは、次のページを指す次のURLまたはカーソルトークンを返します。次のリンクが存在する間、ループを続けます。
次のページの開始位置をサーバーが管理するため、この方式は堅牢です。
all_items = []
next_url = "https://api.example.com/items?limit=100"
while next_url:
resp = requests.get(next_url, timeout=10)
resp.raise_for_status()
data = resp.json()
all_items.extend(data["results"])
next_url = data.get("next") # None when no more pages
print(len(all_items))time.sleepでレート制限を守る
APIには、1秒または1分あたりに送信できるリクエスト数の上限があります。過剰なリクエストを送ると、429 Too Many Requestsが返されたり、アクセスをブロックされたりします。
リクエストの間に短いtime.sleepを入れて、適切な速度を保ち、制限を超えないようにします。
import time
while next_url:
resp = requests.get(next_url, timeout=10)
resp.raise_for_status()
data = resp.json()
all_items.extend(data["results"])
next_url = data.get("next")
time.sleep(0.5) # 2 requests per secondレート制限のヘッダーを読み取る
適切に設計されたAPIでは、X-RateLimit-RemainingやX-RateLimit-Resetのようなヘッダーで、残りの利用可能回数を通知します。
これらを読み取れば、常にスリープするのではなく、制限に近づいたときだけ処理を遅くできます。
remaining = int(resp.headers.get("X-RateLimit-Remaining", 1))
if remaining < 5:
reset = int(resp.headers.get("X-RateLimit-Reset", 1))
print("Near limit, sleeping", reset, "s")
time.sleep(reset)バックオフで429を処理する
429が返された場合、レスポンスに待機時間を示すRetry-Afterヘッダーが含まれていることがよくあります。再試行する前に、その指示に従って待機してください。
resp = requests.get(url, timeout=10)
if resp.status_code == 429:
wait = int(resp.headers.get("Retry-After", 5))
time.sleep(wait)
resp = requests.get(url, timeout=10) # retry oncetqdmで進捗バーを表示する
長時間かかる収集処理は、フィードバックがないと停止したように感じられます。tqdmは任意のイテラブルをラップし、処理速度と予測残り時間(ETA)を含む進捗バーをリアルタイムで表示します。
from tqdm import tqdm
for page in tqdm(range(1, 101), desc="Fetching"):
resp = requests.get(url, params={"page": page}, timeout=10)
all_items.extend(resp.json())
time.sleep(0.2)合計数が分からない場合のtqdm
カーソルによるページネーションでは、最初に全体の件数が分かりません。tqdmを手動カウンターとして使い、ループごとにupdate()を呼び出します。
from tqdm import tqdm
pbar = tqdm(desc="Pages")
while next_url:
resp = requests.get(next_url, timeout=10)
data = resp.json()
all_items.extend(data["results"])
next_url = data.get("next")
pbar.update(1)
pbar.close()増分方式で収集する
非常に大きなデータセットの場合、すべてをメモリ上に保持してはいけません。増分収集では、各ページを受信するたびにディスクへ書き込むため、処理がクラッシュしても進捗をすべて失わずに済みます。
import json
with open("items.jsonl", "w") as f:
while next_url:
resp = requests.get(next_url, timeout=10)
data = resp.json()
for item in data["results"]:
f.write(json.dumps(item) + "\n")
next_url = data.get("next")再開可能な収集
最後に処理したカーソルまたはページ番号を保存しておくと、再実行時に最初からやり直さずに再開できます。これにより、長時間の処理でも障害に強くなります。
import os
start_page = 1
if os.path.exists("checkpoint.txt"):
start_page = int(open("checkpoint.txt").read()) + 1
for page in range(start_page, 1000):
# ... fetch and store ...
open("checkpoint.txt", "w").write(str(page))すべてを組み合わせる
実運用向けの収集ループでは、ページネーション、レート制限のためのスリープ、進捗表示、増分書き込み、チェックポイント保存をすべて組み合わせます。
from tqdm import tqdm
import time, json
with open("out.jsonl", "a") as f:
next_url = "https://api.example.com/items?limit=100"
pbar = tqdm(desc="Pages")
while next_url:
r = requests.get(next_url, timeout=10)
r.raise_for_status()
d = r.json()
for it in d["results"]:
f.write(json.dumps(it) + "\n")
next_url = d.get("next")
pbar.update(1)
time.sleep(0.3)クイックチェック:カーソルによるページネーション
あるAPIが、URLを示す"next"フィールドを返し、最後のページではNoneを返します。
まとめ:大規模なデータセットを収集する
これで、複数のページにまたがるデータセットを収集できるようになりました。
- ページ番号とカーソル(
while next_url)によるページネーション time.sleepとレート制限のヘッダーで429を回避する- スロットリング発生時に
Retry-Afterでバックオフする - 長時間の処理にtqdmの進捗バーを使う
- 障害に備えて増分方式かつ再開可能な形で書き込む
次は、収集したデータを効率的に保存します。
よくある質問
「大規模データセットのページングと収集」レッスンは無料ですか?
はい。「大規模データセットのページングと収集」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Learn AI with Pythonコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Learn AI with Pythonコースには全4レッスンが含まれています。
「大規模データセットのページングと収集」で何を学びますか?
ページング、next_cursor パターン、time.sleep によるレート制限、プログレスバーを扱います。 ブラウザで直接実行するハンズオンコードでLearn AI with Pythonを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
Learn AI with Pythonを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのLearn AI with Pythonは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン2/4です。
「大規模データセットのページングと収集」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このLearn AI with Pythonレッスンでコードを書いて実行できますか?
はい。すべてのLearn AI with Pythonレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- データ収集のための REST API 基礎
- 大規模データセットのページングと収集
- 収集データを効率的に保存する
- 公開データ API の操作