ページネーションと動的コンテンツの処理
次のページへのリンクをたどり、PlaywrightでJavaScriptにより描画されるページを扱います。
「ページネーションと動的コンテンツの処理」はCoddyKit上の無料AI Agentsレッスンです。 これはレッスン3/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはAI Agents学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 AI Agentsコースには全4レッスンが含まれています。
ページネーションの問題
現実のWebサイトの多くは、すべてのデータを1ページに表示しません。負荷を軽減するため、結果は複数のページに分割されます。完全なデータセットを収集するには、エージェントがページネーションを検出してたどる必要があります。
ページネーションには、次ページへのリンクとページ番号を使ったURLパターンという、一般的な2つの形式があります。
次ページへのリンクを検出する
多くのサイトには「Next」ボタンや矢印のリンクがあります。rel='next'を持つアンカータグ、または「Next」のようなテキストを含むアンカータグを見つけて、hrefを抽出します。その後、該当するリンクがなくなるまでループでたどります。
from bs4 import BeautifulSoup
import httpx
def scrape_all_pages(start_url: str) -> list:
results = []
url = start_url
while url:
response = httpx.get(url, timeout=10.0)
soup = BeautifulSoup(response.text, 'html.parser')
# Collect data from this page
for item in soup.select('.result-item'):
results.append(item.text.strip())
# Find the next page link
next_link = soup.find('a', rel='next') or soup.find('a', string='Next')
url = next_link.get('href') if next_link else None
return resultsページ番号を使ったURLパターン
多くのAPIやサイトでは、予測可能なURLパターンが使われています。たとえば、/results?page=1、/results?page=2などです。エージェントは、次ページへのリンクを探すためにDOMを解析せず、これらを直接順番に処理できます。
import httpx
def scrape_paginated_api(base_url: str, max_pages: int = 10) -> list:
all_items = []
for page in range(1, max_pages + 1):
response = httpx.get(
base_url,
params={'page': page, 'per_page': 50},
timeout=10.0
)
response.raise_for_status()
data = response.json()
items = data.get('results', [])
if not items:
break # No more data
all_items.extend(items)
print(f'Page {page}: fetched {len(items)} items')
return all_itemsカーソルベースのページネーション
最新のAPI(GitHub、Slack、Twitter)では、カーソルベースのページネーションが使われています。各レスポンスには、次のページ用のカーサートークンが含まれます。カーサーが存在しなくなるかnullになるまで、次のリクエストにカーサーを渡します。
import httpx
def fetch_with_cursor(url: str, headers: dict) -> list:
all_data = []
cursor = None
while True:
params = {'cursor': cursor} if cursor else {}
response = httpx.get(url, headers=headers, params=params, timeout=10.0)
response.raise_for_status()
data = response.json()
all_data.extend(data.get('items', []))
cursor = data.get('next_cursor') # None when done
if not cursor:
break
return all_data静的コンテンツと動的コンテンツ
初期HTMLが配信された後、JavaScriptによってコンテンツを読み込むページがあります。通常のHTTPクライアントが受け取るのは空の外枠だけで、実際のデータはブラウザ内でJSによって挿入されます。
このようなページでは、Playwrightなどのツールが実際のブラウザエンジンを動かし、JavaScriptの実行を待ってからコンテンツを抽出します。
Playwrightのインストールとインポート
pip install playwrightでPlaywrightをインストールし、playwright install chromiumを実行してブラウザをダウンロードします。非同期のエージェントワークフローでは、async_playwright()を使用します。
# Installation (run in terminal):
# pip install playwright
# playwright install chromium
from playwright.async_api import async_playwright
import asyncio
async def fetch_dynamic(url: str) -> str:
async with async_playwright() as p:
browser = await p.chromium.launch(headless=True)
page = await browser.new_page()
await page.goto(url)
html = await page.content() # Full rendered HTML
await browser.close()
return html
# html = asyncio.run(fetch_dynamic('https://example.com'))動的コンテンツの読み込みを待機する
JavaScriptを使うページでは、データが非同期に読み込まれることがよくあります。コンテンツを抽出する前に特定の要素が表示されるまでPlaywrightに待機させ、必要なデータが実際にDOMに存在することを確実にします。
from playwright.async_api import async_playwright
async def scrape_dynamic_table(url: str) -> list:
async with async_playwright() as p:
browser = await p.chromium.launch(headless=True)
page = await browser.new_page()
await page.goto(url)
# Wait for the table to appear in the DOM
await page.wait_for_selector('table.results', timeout=10000)
html = await page.content()
await browser.close()
from bs4 import BeautifulSoup
soup = BeautifulSoup(html, 'html.parser')
return [td.text for td in soup.select('table.results td')]ページをクリックして操作する
Playwrightでは、クリック、フォームへの入力、スクロール、キーボード入力など、ユーザーの操作をシミュレートできます。これにより、エージェントはログインフローやドロップダウン、無限スクロールのページを操作できるようになります。
from playwright.async_api import async_playwright
async def click_load_more(url: str) -> str:
async with async_playwright() as p:
browser = await p.chromium.launch(headless=True)
page = await browser.new_page()
await page.goto(url)
# Click the 'Load More' button
load_more = page.locator('button:text("Load More")')
if await load_more.count() > 0:
await load_more.click()
await page.wait_for_timeout(2000) # wait 2s for content
html = await page.content()
await browser.close()
return html無限スクロールに対処する
スクロールすると、さらにコンテンツを読み込むサイトがあります。Playwrightでは、こうした読み込みを発生させるためにスクロールをシミュレートできます。繰り返しスクロールし、そのたびに新しいコンテンツが表示されたかを確認します。
from playwright.async_api import async_playwright
async def scrape_infinite_scroll(url: str, scroll_count: int = 5) -> str:
async with async_playwright() as p:
browser = await p.chromium.launch(headless=True)
page = await browser.new_page()
await page.goto(url)
for _ in range(scroll_count):
await page.evaluate('window.scrollTo(0, document.body.scrollHeight)')
await page.wait_for_timeout(1500) # wait for new content
html = await page.content()
await browser.close()
return htmlPlaywrightとBeautifulSoupを組み合わせる
Playwrightでページをレンダリングして完全なHTMLを取得したら、それをBeautifulSoupに渡して簡単に抽出できます。これにより、両ライブラリの長所を組み合わせられます。
from playwright.async_api import async_playwright
from bs4 import BeautifulSoup
async def extract_js_rendered_data(url: str) -> list:
async with async_playwright() as p:
browser = await p.chromium.launch(headless=True)
page = await browser.new_page()
await page.goto(url)
await page.wait_for_selector('.product-card')
html = await page.content()
await browser.close()
soup = BeautifulSoup(html, 'html.parser')
products = []
for card in soup.select('.product-card'):
products.append({
'name': card.select_one('.name').text.strip(),
'price': card.select_one('.price').text.strip()
})
return products適切なツールを選ぶ
すべてのページにPlaywrightが必要なわけではありません。動作する中で最もシンプルな方法を使用してください。
- 静的HTML:httpx + BeautifulSoup(高速で、ブラウザのオーバーヘッドがない)
- ページネーションのあるJSON API:ページ番号やカーサーのパラメーターを指定したhttpx
- JSでレンダリングされるコンテンツ:非同期のPlaywright(低速だが、より高機能)
まずは必ず静的方法から始め、必要な場合にのみPlaywrightを使用してください。
理解度チェック:ページネーションと動的コンテンツ
ページネーションと動的コンテンツの処理についての理解度を確認しましょう。
振り返り:ページネーションと動的コンテンツ
これで、エージェントはWebコンテンツのあらゆる形式に対応できるようになりました。
- 次ページへのリンクをたどるか、URLのページパラメーターを順番に処理する
- 最新のAPIのページネーションにはカーサートークンを使用する
- JavaScriptでレンダリングされるページには
async_playwright()を使用する page.wait_for_selector()で要素の表示を待機する- PlaywrightとBeautifulSoupを組み合わせて簡単に抽出する
必ず最もシンプルな方法から始め、静的方法で対応できない場合にのみPlaywrightへ切り替えてください。
よくある質問
「ページネーションと動的コンテンツの処理」レッスンは無料ですか?
はい。「ページネーションと動的コンテンツの処理」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、AI Agentsコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 AI Agentsコースには全4レッスンが含まれています。
「ページネーションと動的コンテンツの処理」で何を学びますか?
次のページへのリンクをたどり、PlaywrightでJavaScriptにより描画されるページを扱います。 ブラウザで直接実行するハンズオンコードでAI Agentsを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
AI Agentsを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのAI Agentsは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン3/4です。
「ページネーションと動的コンテンツの処理」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このAI Agentsレッスンでコードを書いて実行できますか?
はい。すべてのAI Agentsレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- エージェント向けHTTPクライアント:httpxとrequests
- BeautifulSoupによるHTML解析
- ページネーションと動的コンテンツの処理
- 適切なスクレイピングの実践