動的ウェブサイトのスクレイピング
動的ウェブサイトは、初期ページロードの後にJavaScriptを使用してコンテンツを読み込みます。このガイドでは、FourAのbrowser endpointを使用してこれらのサイトからデータを収集する方法を説明します。
課題
JavaScriptを多用するウェブサイトに標準的なHTTP requestを送信すると、HTMLのシェルは取得できますが、実際のコンテンツは取得できません。必要なデータ(商品リスト、価格、検索結果など)は、ブラウザでページがレンダリングされた後にJavaScriptによって読み込まれます。
これは、React、Vue、Angular、Next.jsなどのモダンなフレームワークでますます一般的になっています。
解決策:browser request
FourAのbrowser endpoint(POST /api/browser/)は、以下の処理を行うChromeブラウザインスタンスでURLを開きます。
- ページを読み込む
- すべてのJavaScriptを実行する
- コンテンツがレンダリングされるのを待つ
- 完全にレンダリングされたHTMLを返す
ステップ 1:必要な情報の特定
requestを送信する前に、ブラウザでターゲットページにアクセスし、DevTools(F12)を使用して、コンテンツが読み込まれたことを確認できるテキストや要素を見つけます。例えば、以下のようなものです。
- JSのレンダリング後に表示される商品名
- レンダリングされたHTML内の
product-gridのようなCSSクラス - データが読み込まれたときにのみ表示される「results」のようなテキスト文字列
ステップ 2:browser requestの送信
curl -X POST https://eu.api.foura.ai/api/browser/ \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/products",
"timeout_ms": 15000,
"checkText": "product-grid"
}'
checkText オプションは、レンダリングされたページに文字列「product-grid」が表示されることを確認するようFourAに指示します。表示されないままタイムアウトに達した場合、requestは失敗し、コンテンツが読み込まれなかったことがわかります。
ステップ 3:HTMLのパース
responseの body フィールドには、完全にレンダリングされたHTMLが含まれています。お好みのライブラリでパースしてください。
Python(BeautifulSoup)
import requests
from bs4 import BeautifulSoup
resp = requests.post("https://eu.api.foura.ai/api/browser/", headers={
"X-API-Key": "YOUR_API_KEY",
"Content-Type": "application/json"
}, json={
"url": "https://example.com/products",
"timeout_ms": 15000,
"checkText": "product-grid"
})
html = resp.json()["body"]
soup = BeautifulSoup(html, "html.parser")
for product in soup.select(".product-card"):
name = product.select_one(".product-name").text.strip()
price = product.select_one(".product-price").text.strip()
print(f"{name}: {price}")
Node.js(cheerio)
import * as cheerio from 'cheerio';
const resp = await fetch('https://eu.api.foura.ai/api/browser/', {
method: 'POST',
headers: { 'X-API-Key': 'YOUR_API_KEY', 'Content-Type': 'application/json' },
body: JSON.stringify({
url: 'https://example.com/products',
timeout_ms: 15000,
checkText: 'product-grid'
})
});
const { body: html } = await resp.json();
const $ = cheerio.load(html);
$('.product-card').each((i, el) => {
console.log($(el).find('.product-name').text(), $(el).find('.product-price').text());
});
トラブルシューティング
コンテンツがまだ空ですか?
- ページが実際にJavaScriptレンダリングを使用しているか確認します(「ソースの表示」とDevToolsを比較)
timeout_msを増やす:一部のページは読み込みに時間がかかります- ページが認証やcookieを必要としているか確認します(
cookiesパラメータを使用)
CAPTCHAページが表示されますか?
- 単一のHTTP requestの場合は、自動IPローテーションのためにproxy endpoint(
POST /api/proxy/)に切り替えます。 - browser requestにproxyローテーションを追加するには、proxy endpointでラップするのではなく、browser endpointの
proxyパラメータを使用します。proxy endpointは単一のHTTP requestのみをラップし、browser requestはラップしません。
curl -X POST "https://eu.api.foura.ai/api/browser/" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"url": "https://example.com", "proxy": "http://proxy-url:port"}'
次のステップ
- 適切なEndpointの選択: browserと単一の使い分け
- 競合他社の価格監視: 価格追跡の完全なチュートリアル
- アンチボット保護: 保護されたサイトの処理