ウェブスクレイピングを理解する:実践的なPythonガイド
Lead Scraping Automation Engineer
TL;DR:
- GrokのAPIはOpenAIを流暢に扱うため、ドロップインの抽出エンジンになります。 公式のOpenAI Python SDKを
https://api.x.ai/v1に向けることで、モデルはページテキストをJSONレコードに変換し、temperature=0およびresponse_format={"type": "json_object"}の設定が可能です。 - Grokが行わないことは取得です。 モデルはブラウザやセッションを持たず、xAIのサーバーサイドWeb検索ツールはリアルタイムの結果をもとに回答を提供し、大量のページ抽出はあなたの仕事に残ります。
- このギャップは1つのスクリプトで明らかです。 JavaScriptでレンダリングされたデモページに対する通常のGETリクエストには0の引用要素しか含まれず、
js_renderを使用してScrapeless Universal Scraping APIを通じた同一URLでは10の引用がすべて含まれています — そして、そのレンダリングされたHTMLがGrokが抽出するものです。 - このガイドでの抽出は実際の運用です、仮説ではありません。 レンダリングされたページに対するライブ実行は、著者とタグ配列がそのまま残る10の引用をすべて返しました — 全体で3,211トークンが掛かりました。
- まだxAIキーを持っていませんか?同じリクエストがOpenRouterを通じて実行されます。 同じOpenAI SDKですが、異なる
base_urlとモデル文字列を使用します。このガイドでは両方のパスを示します。 - 取得側でのスタートは無料です。 app.scrapeless.comでScrapeless APIキーを作成してください。
Grokはウェブサイトをスクレイピングできますか?
Grokはあなたが渡すページを読み取り、要求したフィールドを正確に返しますが、スクレイピングのボリュームでそのページを取得することはできません。これがすべての「Grokウェブスクレイピング」設定の二つの半分であり、それを混同することでプロジェクトが停滞します。xAI APIは言語モデルを公開しています — これは特に接続が容易であるため、エンドポイントはOpenAIと同じリクエスト形式を受け付けるからです — しかし、HTTP取得、JavaScriptレンダリング、セッション状態、アクセスに関する課題はその外にあります。
xAIはサーバーサイドWeb検索ツールを提供しており、それに関して誠実な表現が必要です:それはGrokにライブウェブを検索し、回答を得ることを可能にします。これは質問応答のための取得です。どのページが取得されるか、どのようにレンダリングされるか、また処理できるページの数についてコントロールを提供しない — スクレイピングパイプラインが構築される三つの要素です。
したがって、動作するアーキテクチャは二層です:忠実なレンダリングされたHTMLを返す取得層と、それをレコードに変換するGrokの抽出層。コードに入る前にもう一つの明確な定義があります:このガイドはGrokをウェブに向けます。スクレイパーをGrokに向ける — その回答をデータとしてキャプチャすること — は逆の仕事であり、Grok Scraper APIガイドやLLMスクレイパーの説明でカバーされています。
インストール
全体のツールチェーンはOpenAI SDKプラスrequestsです — このガイドが基づいているバージョンはopenai 2.34.0および現在のrequestsです:
bash
pip install "openai==2.34.0" requests
設定
キーは環境に保管し、ソース内には決して保存しません:
bash
export XAI_API_KEY="xai-your_key"
export SCRAPELESS_API_KEY="sk_your_scrapeless_key"
Grokが実際に読めるページを取得する
抽出の質は取得の忠実度によって制約されるため、ほとんどのGrokチュートリアルの終わりで始めてください。JavaScriptでレンダリングされたページでは、通常のHTTPクライアントが受け取るドキュメントは、リーダーが見るドキュメントではありません — コンテンツは、スクリプトがDOMを構築した後にのみ到着します。これは、HTMLスクリプティング仕様によって定義されたライフサイクルです。一つのスクリプトが違いを示し、抽出に価するバージョンを保存します:
python
# fetch_rendered.py — 通常のGET vs サーバーサイドレンダリング、同一のURL
import os
import requests
URL = "https://quotes.toscrape.com/js/"
MARKER = '<span class="text"'
plain = requests.get(URL, timeout=60).text
print(f"plain GET: {len(plain):,} 文字 | 引用要素: {plain.count(MARKER)}")
resp = requests.post(
"https://api.scrapeless.com/api/v1/unlocker/request",
headers={
"Content-Type": "application/json",
"x-api-token": os.environ["SCRAPELESS_API_KEY"],
},
json={
"actor": "unlocker.webunlocker",
"input": {"url": URL, "method": "GET", "js_render": True},
},
timeout=120,
)
resp.raise_for_status()
rendered = resp.json().get("data", "")
print(f"レンダリングされた: {len(rendered):,} 文字 | 引用要素: {rendered.count(MARKER)}")
with open("page.html", "w", encoding="utf-8") as f:
f.write(rendered)
実行結果は、プレーンフェッチでは「引用要素: 0」と表示され、レンダリングされたものでは「引用要素: 10」と表示されます。レンダリング、アンロック、およびプロキシルーティングはすべて、その1つのPOSTでサーバーサイドで行われます — ユニバーサルスクレイピングAPI がフェッチレイヤーであり、page.html はモデルが抽出できるものになっています。
基本的な実装: Grokを抽出器として使用
xAIエンドポイントは、標準のOpenAIチャットコンプリーションリクエストを受け取ります。二つのパラメータが信頼性を持たせます: temperature=0は、実行ごとに出力を安定させ、JSONモードにより解析可能になります。システムメッセージ内に必要なキーを正確に指定し、欠損値に対してモデルに何をすべきか教えてください。
注: このブロックは、クレジット付きの
XAI_API_KEYが必要です — このガイドではこの前提を仮定していません。次のセクションでは、キャプチャされた出力を使用して、OpenRouterを介して同一の抽出をライブで実行します。
python
# extract_grok.py — xAI APIを通じたGrok抽出(XAI_API_KEYが必要)
import json
import os
from openai import OpenAI
client = OpenAI(
base_url="https://api.x.ai/v1",
api_key=os.environ["XAI_API_KEY"],
)
page_html = open("page.html", encoding="utf-8").read()
completion = client.chat.completions.create(
model="grok-4.5",
temperature=0,
response_format={"type": "json_object"},
messages=[
{
"role": "system",
"content": '全ての引用を抽出します。JSONでのみ返信してください: '
'{"quotes":[{"text":str,"author":str,"tags":[str]}]}. 欠損値にはnullを使用してください。',
},
{"role": "user", "content": page_html},
],
)
data = json.loads(completion.choices[0].message.content)
print(f"抽出された引用の数: {len(data['quotes'])}個")
grok-4.5はxAIの現在の文書で中心となっているモデルです。お使いのアカウントが運用しているレベルに応じて置き換えてください。リクエストの形は変わりません。
xAIキーがない場合? OpenRouterを通じて同じリクエストを実行
リクエストがOpenAIスタイルで端から端まで形成されているため、アグリゲーターキーは2つの変更で機能します: base_url とモデルストリングです。これは、このガイドが実際に実行したバリアントです — フェッチと抽出が1つの自己完結型スクリプトで行われます。
python
# extract_openrouter.py — OpenRouterを介して実行された同じ抽出
import json
import os
import requests
from openai import OpenAI
resp = requests.post(
"https://api.scrapeless.com/api/v1/unlocker/request",
headers={
"Content-Type": "application/json",
"x-api-token": os.environ["SCRAPELESS_API_KEY"],
},
json={
"actor": "unlocker.webunlocker",
"input": {"url": "https://quotes.toscrape.com/js/", "method": "GET", "js_render": True},
},
timeout=120,
)
resp.raise_for_status()
page_html = resp.json().get("data", "")
client = OpenAI(
base_url="https://openrouter.ai/api/v1",
api_key=os.environ["OPENROUTER_API_KEY"],
)
completion = client.chat.completions.create(
model="x-ai/grok-4.20",
temperature=0,
response_format={"type": "json_object"},
messages=[
{
"role": "system",
"content": '全ての引用を抽出します。JSONでのみ返信してください: '
'{"quotes":[{"text":str,"author":str,"tags":[str]}]}. 欠損値にはnullを使用してください。',
},
{"role": "user", "content": page_html},
],
)
data = json.loads(completion.choices[0].message.content)
print(f"レンダリングされたページから抽出された引用の数: {len(data['quotes'])}個")
print(json.dumps(data["quotes"][0], ensure_ascii=False))
ライブ実行では、すべての10個の引用が抽出され、最初のものが印刷されました:
text
レンダリングされたページから抽出された引用の数: 10個
{"text": "“我々が創造した世界は我々の思考のプロセスである。それを変えずに我々の思考を変えることはできない。”", "author": "アルバート・アインシュタイン", "tags": ["変化", "深い思考", "思考", "世界"]}
著者とタグの配列はそのまま渡された、そして全体の呼び出しは3,211トークンを消費しました。これが全体のスクレイパーです: フェッチのための1回のPOST、抽出のための1回のコンプリーション、どこにもセレクタなし。
無料プランであなたのAPIキーを取得してください: app.scrapeless.com
高度なパターン
- スキーマをシステムメッセージに固定し、ユーザープロンプトにはしない。 ページのHTMLはユーザーのターンに入れ、契約はページ間ループを生き残るシステムのターンに残ります。
- プロンプトではなくPythonでループを行う。 一回のコンプリーションで一つのページを維持することで、記録のバラつきを防ぎ、特定のURLに失敗の原因を帰属させることができます。
- 可能な限り少ないページを送信する。 Grokは送信された全ドキュメントを読み取りますので、トークン消費を大幅に削減するためには、コンテンツコンテナを分離するか、HTMLの代わりにMarkdownを取得します。
- タグとリストを明示的に扱う。 スキーマで
tags:[str]と名付けることで、上記の実行でクリーンな配列が生成されました; リストフィールドは説明を省略すると、モデルはそれらを文字列にフラット化します。
トラブルシューティング
- JSONではなく散文。
response_format={"type": "json_object"}を省略しました — それがあるとエンドポイントは出力を制約します; それがない場合、あなたは善意を解析しています。 - 期待される10レコード、3つ返却。 モデルを非難する前に、取得したものをチェックしてください: フェッチスクリプトと同じ方法でHTML内の既知の要素をカウントします。ほぼ空のフェッチはレンダリングの問題を意味し、
js_renderでフェッチレイヤーで解決されます。 - 同一入力で異なる出力。
temperature=0に設定してください; 抽出は創造性のタスクではありません。 - コストが増加傾向。 トークンの消費は入力サイズに追従します。ページをトリミングし、バッチ処理せず、上記の実行が報告するようにページあたりのトークンカウントに注意を払います。
結論
Grokはネットワークを見ない層としてスクレイパーでの位置を確保します: OpenAI形式のリクエスト、決定的な設定、一ページ入り、一つのJSONオブジェクト出力。このすべてが可能かどうかを決定するのはフェッチです — 最初のスクリプトの0対10の出力がその質問を決定し、一つのサーバーレンダリングされたPOSTがギャップを埋めます。両者を結線し、デモページの10の引用が検証されたレコードとして届きます、タグなどすべて。
Grokにリアルページを供給する準備はできましたか?
このガイドのフェッチレイヤーは ユニバーサルスクレイピングAPI でのページごとに1つのPOSTです — プランとボリュームは 料金ページ にあります、そして 開発者ドキュメント は unlocker.webunlocker パラメーターをカバーします。 app.scrapeless.com で無料プランのキーを作成し、書かれている通りに両方のスクリプトを再実行してください。
よくある質問
Q: Grokは自力でウェブサイトをスクレイピングできますか?
いいえ。Grok APIは提供されたテキストから抽出します; リクエストを発行したり、JavaScriptをレンダリングしたり、セッションを保持することはできません。ウェブ検索ツールは生のウェブを読み取って回答を得ますが、ページの選択、レンダリングの忠実度、ボリュームはあなたの制御を超えています — スクレイピングパイプラインには独自のフェッチレイヤーが必要です。
Q: Grokの内蔵ウェブ検索はウェブスクレイピングと同じものですか?
異なる仕事です。検索ツールはモデルが質問に答えられるようにコンテキストを取得します; スクレイピングは特定のページを取得して、選択したボリュームで特定のフィールドを抽出します。回答が必要なときはツールを使用し、データが必要なときはこのガイドの2レイヤーパイプラインを使用します。
Q: Grokスクレイパーとはどう違いますか?
方向性です。ここではGrokがパーサーで、ウェブがターゲットです。Grokスクレイパーはそれを逆転させます — Grokの自らの回答を構造化されたデータとしてキャプチャし、Scrapelessはそれをアクターとして送信します; 紹介でリンクされたGrokスクレイパーAPIガイドがその仕事をカバーしています。
Q: 抽出にどのGrokモデルを使用すればいいですか?
あなたのスキーマを保持する最も安価なものです。厳格なJSON契約と temperature=0 での抽出は推論が重いタスクでないため、小さなもので始めてください — このガイドのライブ実行はLower priced Grok tierをOpenRouter経由で使用し、すべての10レコードを正確に返しました — フィールドが間違った値で戻ってきた場合のみ、上に移動してください。
Q: Grokを使用したスクレイピングは合法ですか?
モデルは収集のルールを変更しません。公開ページのみをフェッチし、サイトの利用規約と ロボット排除プロトコル で標準化されたロボット指示を尊重し、ボリュームを制限し、適用される法律の下で個人データを処理してください — そしてモデル面でのxAIの利用規約も遵守してください。
Scrapelessでは、適用される法律、規制、およびWebサイトのプライバシーポリシーを厳密に遵守しながら、公開されているデータのみにアクセスします。 このブログのコンテンツは、デモンストレーションのみを目的としており、違法または侵害の活動は含まれません。 このブログまたはサードパーティのリンクからの情報の使用に対するすべての責任を保証せず、放棄します。 スクレイピング活動に従事する前に、法律顧問に相談し、ターゲットウェブサイトの利用規約を確認するか、必要な許可を取得してください。



