AI

GLMによるウェブスクレイピング:テキストとビジュアルデータの抽出

GLM-5.3とBright DataのWeb Unlockerを組み合わせたAI駆動ウェブスクレイピング。一般的な障壁を回避しながら、テキストとビジュアルデータを自動抽出します。
1 分読
Web Scraping with GLM

この記事では以下の内容をご紹介します:

  • GLM-5.3とGLM-5.3-FlashがLLMを活用したウェブスクレイピングタスクにおいて重要な進歩を示す理由。
  • ウェブデータ抽出システム構築における主な障壁と、Bright Data Web Unlocker APIによる解決策。
  • PythonでGLMを使用したAI搭載ウェブスクレイピングのステップバイステップ実装。
  • GLM-5.3のマルチモーダル機能を使用したビジョンベースのウェブスクレイピングの実行方法。

それでは始めましょう!

ウェブデータ抽出におけるGLMモデルの利点

現代のLLMはウェブスクレイピングのアプローチに革命をもたらしました。生のHTMLマークアップを処理するための手動パースルーティンを実装する代わりに、AIモデルを活用して自動的に抽出処理を行うことができます。これにより、CSSセレクターベースのアプローチとXPath式マッチングに固有の脆弱性が解消されます。

必要なのは、取得したいデータ要素を指定した適切に作成されたプロンプトだけです。わずか数行のコードで、任意のウェブページから整理されたデータを識別・抽出するようLLMに指示できます。このAI駆動の手法により、ページ構造が変化しても大幅に堅牢なウェブスクレイパーを作成できます。

この文脈において、GLM-5.3はテキストベースの情報取得と構造化データ生成に優れています。そしてGLM-5.3-Flashはビジョン機能を備えており、ウェブページのスクリーンショットやグラフィック要素の分析が可能です。

さらなる背景情報については、以下の関連リソースをご参照ください:

  1. AI駆動ウェブスクレイピング手法の一般原則。
  2. GPT Visionを使用したビジュアルデータ抽出へのAIの応用

AIウェブスクレイピングにおける主な課題

AIベースの抽出はページマークアップの変更への感度を低下させます。それでも、AIウェブスクレイピングで遭遇する主な技術的課題は、従来のウェブスクレイピングと概ね一致しています。

主な問題は、JavaScriptのレンダリング、ボット対策検出システム、デバイスフィンガープリンティング技術、リクエストレート制限、CAPTCHA、IPレピュテーションの問題です。結局のところ、LLMがウェブページを処理する前に、まずそのコンテンツを取得する必要があります。これにはプログラムによるアクセスを防ぐために設計された様々な保護措置への対応が必要です。

したがって、AI搭載の抽出はウェブページコンテンツを大規模に取得するという根本的な困難を排除しません。確かなのは、プロセスにAIを追加することで新たな考慮事項が生まれることです。特に、トークン消費が重要な要素になります。

大量のHTMLドキュメントをGLM-5.3のような高度なモデルに送信すると、かなりのコストが蓄積される可能性があります。最適な解決策は、生のHTMLをLLM向けに最適化されたMarkdown形式に変換することです。

ウェブページを構造化されたMarkdownに変換することで、重要な情報とレイアウト階層を保持しながら、不要なトークン消費を大幅に削減できます。この変換により、ヘッダー、番号付きリスト、画像URLとキャプション、ハイパーリンクがLLMが効率的に処理できる形式で保持されます。詳細については、HTMLからMarkdownへの変換に関するチュートリアルをご覧ください。

Bright Data Web Unlocker API:解決策

Bright DataのWeb Unlocker APIは、ウェブスクレイピングの根本的な課題に対するオールインワンソリューションを提供します。従来のパースとAI搭載パースのどちらを適用したい場合でも同様です。

Web Unlocker APIはターゲットURLを受け取り、すべてのボット対策を処理しながらレンダリングされたコンテンツを返すエンドポイントとして機能します。特に、CAPTCHA保護をバイパスし、JavaScriptを多用するページを処理し、ブラウザフィンガープリンティング検出を回避し、IPをローテーションし、その他多くの機能を提供します。Bright Dataのボット対策バイパスアプローチの詳細をご覧ください。

さらに、Web Unlocker APIは取得データを複数の出力形式で返す柔軟性を提供します:

  1. LLM向けに最適化されたMarkdown表現
  2. レンダリングされたページのスクリーンショットキャプチャ

その結果、Web Unlocker APIリクエストからのレスポンスデータは、GLM-5.3やGLM-5.3-FlashなどのLLMを使用した後続のテキストベースまたはビジョンベースのデータ抽出への理想的な入力として機能します。

注意:Web Unlocker APIはBright Dataの無料ティアに含まれており、毎月5,000件の無料抽出リクエストが付与されます。

Web Unlocker APIが他のウェブスクレイピングAPIと一線を画すのは、Bright Dataが提供するエンタープライズグレードのインフラです。これには4億以上のレジデンシャルIPアドレス、無制限の同時実行、99.99%のアップタイム、99.95%の成功率が含まれます。このようなインフラにより、信頼性が高くスケーラブルなプログラムによるデータ抽出が可能になります。

PythonでGLM-5.3を使用したAI搭載ウェブスクレイパーの構築方法

このガイドセクションでは、GLM-5.3をAI搭載データパースに活用するPythonスクリプトの開発方法を学びます。

このスクリプトはこの特定のIKEA製品ページからのデータ収集に焦点を当てています:

ターゲットIKEA製品ページ

AIベースのデータパースの主な利点は、同じコードをすべてのIKEA製品ページに適用できることです。個々のレイアウトやデザインのバリエーションに関係なく適用可能です。

ワークフローは以下のとおりです:

  1. Bright Data Web Unlocker APIがターゲットIKEA製品ページを取得し、そのコンテンツをLLM向けに最適化されたMarkdownとして出力します。
  2. GLM-5.3がOpenAI互換のZ.ai APIを通じてMarkdownコンテンツを受け取り、製品情報を抽出します。
  3. 事前定義されたJSONスキーマに準拠した結果の出力がディスクにエクスポートされます。

注意:大規模な構造化IKEAデータが必要な本番システムには、Bright DataのIKEA スクレイパーAPIの使用をご検討ください。

以下の手順に従ってください!

前提条件

以下が利用可能であることを確認してください:

Web Unlockerセットアップドキュメントをご参照ください。

Bright Data APIキーの取得に関する公式ガイドに従ってください。

このガイドでは、Web Unlocker APIゾーンがweb_unlockerという名前であることを前提とします:

「web_unlocker」Web Unlocker APIに注目

また、Z.ai APIキーは次のような形式になります:

Z.ai APIキーに注目

ステップ#1:Pythonプロジェクトを初期化する

GLMスクレイピングプロジェクト用の新しいディレクトリを作成します:

mkdir glm-scraper

このディレクトリに移動し、Python仮想環境を追加します:

cd glm-scraper
python -m venv .venv

Visual Studio CodePyCharmなどの好みのPythonエディタでプロジェクトディレクトリを開きます。

プロジェクトルートにscraper.pyファイルを追加します:

glm-scraper
├─── .venv/
└─── scraper.py # <-----

このファイルにはGLMモデルを使用したAI搭載データ抽出のPythonコードが含まれます。

次に、仮想環境を有効化します。LinuxまたはmacOSシステムでは、以下を実行します:

source .venv/bin/activate

Windowsプラットフォームでは、以下を実行します:

.venv\Scripts\activate

有効化が完了したら、必要なプロジェクト依存関係をすべてインストールします:

pip install dotenv requests openai pydantic

必要なパッケージは以下のとおりです:

  • dotenv:APIキーを保存するための環境変数管理。
  • requests:Bright Data Web Unlocker APIとの通信用HTTPクライアント。
  • openai:GLMアクセス用OpenAI互換Z.ai APIにアクセスするためのOpenAI互換クライアント。
  • pydantic:出力スキーマのデータモデル定義と検証フレームワーク。

よくできました!PythonプロジェクトがGLMを使用したウェブスクレイピングの準備ができました。

ステップ#2:環境変数の読み込みを追加する

GLMスクレイパーはBright DataやZ.aiのAPIを含む外部サービスとの認証が必要です。これらの統合にはAPIキーが必要であり、セキュリティ上の理由からソースコード内に公開すべきではありません。

代わりに、環境設定ファイルにAPIキーを保管し、実行時に読み込みます。python-dotenvパッケージは.envファイルから環境変数を読み込むことでこのプロセスを簡素化します。

python-dotenvを使い始めるには、scraper.pyの先頭に以下のコードを追加します:

from dotenv import load_dotenv

# .envファイルから環境変数を読み込む
load_dotenv()

次に、プロジェクトルートに.envファイルを作成します:

glm-scraper
├─── .venv/
├─── .env       # <-----
└─── scraper.py

ヒント:実際のリポジトリでは、.env.gitignore設定に含めて、誤った認証情報の公開を防止してください。

APIの認証情報を入力します:

BRIGHT_DATA_API_KEY="<YOUR_BRIGHT_DATA_API_KEY>"
ZAI_API_KEY="<YOUR_ZAI_API_KEY>"

以下を置き換えてください:

  • <YOUR_BRIGHT_DATA_API_KEY>をBright DataのAPI認証情報に。
  • <YOUR_ZAI_API_KEY>をZ.ai APIキーに。

次に、Pythonのos.getenv()を使用してこれらの環境変数をスクリプトに読み込みます:

import os

# 環境変数から必要なシークレットを読み込む
ZAI_API_KEY = os.environ.get("ZAI_API_KEY")
BRIGHT_DATA_API_KEY = os.environ.get("BRIGHT_DATA_API_KEY")

素晴らしい!PythonスクリプトでAPIキーへの安全なアクセスが確保されました。

ステップ#3:Web Unlocker APIでターゲットウェブページをMarkdown形式で取得する

AI搭載スクレイピングの最初のフェーズは、ターゲットページをLLM対応のMarkdown形式で取得することです。Bright DataのWeb Unlocker APIがその最もシンプルな方法を提供します。

Web Unlocker統合の詳細については、公式ドキュメントをご参照ください。またはBright DataのPython統合例をご確認ください。

requestsライブラリを使用してWeb UnlockerにHTTP POSTリクエストを送信し、ターゲットページをMarkdownとしてレンダリングして取得します:

import requests

# Web Unlockerの認証ヘッダーを設定する
headers = {
    "Content-Type": "application/json",
    "Authorization": f"Bearer {BRIGHT_DATA_API_KEY}"
}

# Web Unlocker API呼び出しのリクエストペイロードを定義する
payload = {
    "zone": "web_unlocker", # Web UnlockerゾーンNameに置き換える
    "url": "https://www.ikea.com/us/en/p/kallax-shelf-unit-white-20631663/", # スクレイピングするIKEA製品ページのURL
    "format": "raw",
    "country": "us",
    "data_format": "markdown" # Markdown形式の出力をリクエスト
}

# ターゲットページのアンロックされたコンテンツを取得する
web_unlocker_response = requests.post(
    "https://api.brightdata.com/request",
    json=payload,
    headers=headers
)
markdown_page = web_unlocker_response.text

Python HTTPシントラックスに慣れていない場合は、Requestsの包括的なガイドをご覧ください。

ボディ内のdata_format="markdown"パラメータに注目してください。この設定はWeb Unlocker APIに対して、生のHTMLを提供する代わりにウェブページをMarkdown形式で出力するよう指示します。

markdown_pageを出力すると、以下が表示されます:

Web Unlocker API呼び出しによって生成された出力

返された出力はターゲットIKEA製品ページのMarkdown変換バージョンです。

Web Unlocker APIがウェブページ取得の障壁を処理する方法に注目してください:

  1. Bright Dataのレジデンシャルプロキシネットワークを通じてターゲットIKEAインフラにアクセスします。
  2. IKEAのアンチスクレイピングシステムなどの一般的なボット対策に対処します。
  3. 完全にレンダリングされたページマークアップを取得します。
  4. HTMLをLLM向けに最適化されたMarkdownに変換して結果を返します。

GLM-5.3テキストベースのデータパースに最適な形式でページ情報を取得できました。先に進む前に、GLMが生成する出力構造を確立しましょう!

ステップ#4:出力JSONスキーマを定義する

GLM-5.3は他のほとんどのLLMと同様、デフォルトでテキスト出力を生成します。これはデータ抽出ワークフローには最適ではありません。目的は生のウェブコンテンツを構造化データに変換することです。

幸いなことに、GLM-5.3 APIはJSONモードによる構造化出力をサポートしています。この機能により、モデルはプレーンなJSON文字列を返すことができます。

注意OpenAIの構造化出力のようにjson_schema引数でスキーマを直接指定することはできませんが、プロンプトで希望するレスポンス構造を記述することができます。これによりモデルはその形式に準拠したJSON文字列を生成するよう強制されます。

Pythonで構造化JSONスキーマを定義する最も便利な方法は、最も人気のあるデータモデリングフレームワークであるPydanticを通じてです。PydanticはPythonクラスを通じてデータ構造を表現し、Z.ai API用のJSON Schema形式に変換できます。

ターゲットIKEAページを調べて必要な情報フィールドを特定することから始めます。この例では、IKEA製品の詳細を取得するPydanticモデルを定義します:

from pydantic import BaseModel, Field
from typing import List, Optional

class IkeaProduct(BaseModel):
    title: Optional[str] = Field(None, description="IKEAウェブサイトに表示される製品の完全なタイトル")
    product_number: Optional[str] = Field(None, description="IKEAの製品記事番号(例:304.247.75)")
    product_type: Optional[str] = Field(None, description="IKEA製品の一般的なタイプ(アームチェア、シェルフユニット、キャビネット、テーブルなど)")
    price: Optional[float] = Field(None, description="現在の一回購入価格")
    currency: Optional[str] = Field(None, description="表示価格に使用される通貨(USDなど)")
    color: Optional[str] = Field(None, description="製品の色または仕上げ(バーチ突板やダークグレーなど)")
    dimensions: Optional[str] = Field(None, description="IKEAが表示する製品全体の寸法(幅、奥行き、高さを含む)")
    materials: Optional[List[str]] = Field(None, description="製品の製造に使用される主な素材")
    rating: Optional[float] = Field(None, description="平均顧客評価(通常5点満点)")
    review_count: Optional[int] = Field(None, description="顧客レビューの総数")
    series: Optional[str] = Field(None, description="製品が属するIKEA製品シリーズ(POÄNGなど)")
    assembly_required: Optional[bool] = Field(None, description="製品に組み立てが必要かどうか")
    is_in_stock: Optional[bool] = Field(True, description="製品が現在購入可能かどうか")

このモデルはIKEA製品情報を明示的な型付きのPydanticフィールドに整理します。GLM-5.3はページコンテンツから一致する値を取得し、このスキーマに準拠したJSON文字列レスポンスとして提供します。

プロのヒント:Web Unlocker APIがページから取得したMarkdownをLLMに渡し、関心のあるすべてのデータポイントを含むPydanticモデルを生成するよう依頼してください。

素晴らしい!GLMウェブスクレイピングに必要なすべてのコンポーネントが揃いました。

ステップ#5:GLM-5.3を使用した自動データパース

Z.ai APIはOpenAI Chat CompletionsおよびResponsesインターフェースと互換性があり、OpenAI Python SDKを介したアクセスが可能です。Z.ai APIの認証情報と適切なAPIベースURLでOpenAIクライアントを設定します。

from openai import OpenAI

# Z.ai APIと対話するためのOpenAIクライアントを初期化する
glm_client = OpenAI(
    api_key=ZAI_API_KEY,
    base_url="https://api.z.ai/api/paas/v4/", # OpenAI Chat Completions互換のGLM APIベースURL
)

次に、Chat Completionsエンドポイントを使用して抽出されたMarkdownをGLM-5.3に送信します:

import json

# 出力スキーマを含むスクレイピングプロンプトを準備する
scraping_prompt = f"""
提供されたMarkdownドキュメントからIKEA製品情報を抽出し、
提供されたJSONスキーマに準拠した構造化データとして返してください。

SCHEMA:
{json.dumps(IkeaProduct.model_json_schema(), indent=2)}

MARKDOWN:
{markdown_page}
"""

# GLM-5.3でウェブデータパースを実行する
response = glm_client.chat.completions.create(
    model="glm-5.3",
    messages=[
        {
            "role": "user",
            "content": [
                {
                    "type": "text",
                    "text": scraping_prompt,
                },
            ],
        }
    ],
    response_format={"type": "json_object"}
)

# 定義されたスキーマ形式に一致する文字列でパースされたデータを取得する
product_data = response.choices[0].message.content

プロンプトには以下を含める必要があります:

  1. ウェブデータ抽出の指示。
  2. ターゲットJSONスキーマ。
  3. Bright DataのWeb Unlocker APIからのMarkdownコンテンツ。

response_formatパラメータは{"type": "json_object"}でJSONモードを有効にします。GLM-5.3はjson_schemaではなくjson_object形式をサポートしていることを覚えておいてください。これはKimiによるウェブスクレイピングなど一部の代替モデルとの重要な違いです。

注意オプションのthinkingおよびreasoning_effortパラメータはGLM-5.3の拡張推論機能を有効にします。高度に複雑なデータパースタスクに対して深い推論を有効にするにはreasoning_effort"max"に設定します。これはページに曖昧または非標準のレイアウトが含まれる場合に特に価値があります。

結果はproduct_dataで、IkeaProductモデルに従って構造化された抽出情報を含むJSON文字列です。出力すると以下が表示されます:

生成されたデータはJSONでIkeaProductモデルと一致している

いいですね!残りのステップはこのJSONデータをディスクに保存することだけです。

ステップ#6:スクレイピングしたデータをディスクに保存する

product_dataproduct.jsonファイルに保存する前に、IkeaProduct Pydanticモデルに対してレスポンスを検証します:

# 定義されたスキーマ形式でパースされたデータを取得する
product_data = response.choices[0].message.content

# JSON文字列をIkeaProductスキーマに対して検証する
product = IkeaProduct.model_validate_json(product_data)

model_validate_json()メソッドはLLMレスポンスが期待されるPydanticスキーマに準拠していることを確認します。レスポンスに無効なデータが含まれているか、定義されたフィールド型と一致しない場合、Pydanticは不正なデータをサイレントに保存する代わりに検証エラーを発生させます。

その後、ディスクに保存します:

# 検証済みのIkeaProductオブジェクトをJSONファイルにエクスポートする
with open("product.json", "w", encoding="utf-8") as f:
    f.write(product.model_dump_json(indent=2))

このスニペットはproduct.model_dump_json()を使用して検証済みのIkeaProductオブジェクトをシリアライズし、product.jsonに書き込みます。結果ファイルにはGLM-5.3によって抽出された構造化IKEA製品データが含まれます。ミッション完了!

ステップ#7:すべてをまとめる

以下はIKEA製品ページ用GLMウェブスクレイパーの完全な実装です:

# pip install dotenv requests openai pydantic

from dotenv import load_dotenv
import os
import requests
from pydantic import BaseModel, Field
from typing import List, Optional
from openai import OpenAI
import json

# .envファイルから環境変数を読み込む
load_dotenv()

# 環境変数から必要なシークレットを読み込む
BRIGHT_DATA_API_KEY = os.environ.get("BRIGHT_DATA_API_KEY")
ZAI_API_KEY = os.environ.get("ZAI_API_KEY")

# 製品情報の出力スキーマ
class IkeaProduct(BaseModel):
    title: Optional[str] = Field(None, description="IKEAウェブサイトに表示される製品の完全なタイトル")
    product_number: Optional[str] = Field(None, description="IKEAの製品記事番号(例:304.247.75)")
    product_type: Optional[str] = Field(None, description="IKEA製品の一般的なタイプ(アームチェア、シェルフユニット、キャビネット、テーブルなど)")
    price: Optional[float] = Field(None, description="現在の一回購入価格")
    currency: Optional[str] = Field(None, description="表示価格に使用される通貨(USDなど)")
    images: Optional[List[str]] = Field(None, description="IKEAウェブサイトの製品画像のURL")
    color: Optional[str] = Field(None, description="製品の色または仕上げ(バーチ突板やダークグレーなど)")
    dimensions: Optional[str] = Field(None, description="IKEAが表示する製品全体の寸法(幅、奥行き、高さを含む)")
    materials: Optional[List[str]] = Field(None, description="製品の製造に使用される主な素材")
    visual_features: Optional[List[str]] = Field(None, description="提供された製品画像で視覚的に確認できる物理的特性(形状、コンポーネント、仕上げ、構成など)")
    rating: Optional[float] = Field(None, description="平均顧客評価(通常5点満点)")
    review_count: Optional[int] = Field(None, description="顧客レビューの総数")
    series: Optional[str] = Field(None, description="製品が属するIKEA製品シリーズ(POÄNGなど)")
    designer: Optional[str] = Field(None, description="IKEAが製品のデザイナーとしてクレジットしている人物")
    max_load: Optional[str] = Field(None, description="最大耐荷重(座面、棚、天板の最大耐荷重など)")
    care_instructions: Optional[List[str]] = Field(None, description="IKEAが推奨するお手入れとクリーニングの手順")
    package_count: Optional[int] = Field(None, description="製品に含まれるパッケージ数")
    package_dimensions: Optional[List[str]] = Field(None, description="製品パッケージの寸法")
    package_weight: Optional[str] = Field(None, description="梱包された製品の重量")
    assembly_required: Optional[bool] = Field(None, description="製品に組み立てが必要かどうか")
    assembly_instructions_url: Optional[str] = Field(None, description="IKEAの公式組み立て説明書のURL")
    safety_information: Optional[List[str]] = Field(None, description="壁への固定や転倒防止要件などの重要な安全情報")
    good_to_know: Optional[List[str]] = Field(None, description="追加のIKEA製品情報と使用上の推奨事項")
    compatible_series: Optional[List[str]] = Field(None, description="製品がコーディネートできると説明されているIKEA製品シリーズや家具ライン")
    accessories: Optional[List[str]] = Field(None, description="製品ページに表示または推奨されているアクセサリーや補完的なIKEA製品")
    category_path: Optional[List[str]] = Field(None, description="製品に至るIKEAカテゴリのパンくずリストパス")
    available_colors: Optional[List[str]] = Field(None, description="同じ製品で利用可能な他の色または仕上げオプション")
    is_in_stock: Optional[bool] = Field(True, description="製品が現在購入可能かどうか")

# Web Unlocker APIの認証ヘッダーを設定する
headers = {
    "Content-Type": "application/json",
    "Authorization": f"Bearer {BRIGHT_DATA_API_KEY}"
}

# Web Unlocker APIスクレイピングリクエストのリクエストペイロードを定義する
payload = {
    "zone": "web_unlocker", # Web UnlockerゾーンNameに置き換える
    "url": "https://www.ikea.com/us/en/p/kallax-shelf-unit-white-20631663/", # スクレイピングするIKEA製品ページのURL
    "format": "raw",
    "country": "us",
    "data_format": "markdown" # ウェブページをMarkdownで取得するため
}

# アンロックされたターゲットページのMarkdownコンテンツを取得する
web_unlocker_response = requests.post(
    "https://api.brightdata.com/request",
    json=payload,
    headers=headers
)
markdown_page = web_unlocker_response.text

# Z.aiモデル用のOpenAIクライアントを初期化する
glm_client = OpenAI(
    api_key=ZAI_API_KEY,
    base_url="https://api.z.ai/api/paas/v4/",
)

# LLM搭載ウェブデータパース用プロンプト
scraping_prompt = f"""
提供されたMarkdownドキュメントからIKEA製品情報を抽出し、
提供されたJSONスキーマに準拠した構造化データとして返してください。

SCHEMA:
{json.dumps(IkeaProduct.model_json_schema(), indent=2)}

MARKDOWN:
{markdown_page}
"""

# GLM-5.3でウェブデータスクレイピングを実行する
response = glm_client.chat.completions.create(
    model="glm-5.3",
    messages=[
        {
            "role": "user",
            "content": [
                {
                    "type": "text",
                    "text": scraping_prompt,
                },
            ],
        }
    ],
    response_format={"type": "json_object"},
)

# 定義されたスキーマ形式でパースされたデータを取得する
product_data = response.choices[0].message.content

# JSON文字列を検証済みのIkeaProductオブジェクトに変換する
product = IkeaProduct.model_validate_json(product_data)

# IkeaProductオブジェクトをJSONファイルにエクスポートする
with open("product.json", "w", encoding="utf-8") as f:
    f.write(product.model_dump_json(indent=2))

有効化された仮想環境で、以下を使用してPythonスクリプトを実行します:

python scraper.py

Web Unlocker APIによるページ取得とGLM-5.3による後続処理には時間がかかります。product.jsonファイルが生成されるまでお待ちください。

プロジェクトのフォルダに表示されたら開くと、以下が確認できます:

GLM-5.3でスクレイピングされたデータを含む「product.json」ファイルの部分ビュー

抽出されたデータと元のIKEA製品ページで利用可能な情報の一致に注目してください。

完成です!Web Unlocker APIはIKEAのボット対策を処理してLLM向けに最適化されたMarkdownコンテンツを提供し、GLM-5.3はそのコンテンツを正常に処理して整理された構造化データに変換しました。

GLM-5.3-Flashを使用したビジョンベースのウェブデータ抽出の実行方法

GLM-5.3はマルチモーダル入力をネイティブにサポートしていないため、テキストベースの入力のみを処理できます。しかし、GLMファミリーの他のモデルはマルチモーダル入力をサポートしており、GLM-5.3-Flash(GLM-4.6Vなど)もその一つです。

テキストベースのページコンテンツをLLMに提供する代わりに、スクリーンショットや画像を提供してGLM-5.3-Flashに構造化情報を抽出するよう依頼できます。

スクレイピング手順は概ね同じです:

  1. Bright Data Web Unlocker APIがターゲットIKEAページのスクリーンショットをキャプチャします。
  2. GLM-5.3-FlashがZ.ai APIを通じてスクリーンショットを受け取り、事前定義されたスキーマに従って製品情報を抽出します。
  3. 抽出されたデータが検証され、構造化JSONとして保存されます。

注意:コアワークフローはほとんど変わらないため、このセクションはビジュアルデータ抽出に必要な変更点に焦点を当てています。前述のすべての前提条件とセットアップ手順は引き続き有効です。

ステップ#1:ページスクリーンショットを取得する

MarkdownではなくページスクリーンショットをWeb Unlocker APIリクエストで取得するよう調整します:

# Web Unlockerの認証ヘッダーを設定する
headers = {
    "Content-Type": "application/json",
    "Authorization": f"Bearer {BRIGHT_DATA_API_KEY}"
}

# Web Unlocker API呼び出しのリクエストペイロードを定義する
payload = {
    "zone": "web_unlocker", # Web UnlockerゾーンNameに置き換える
    "url": "https://www.ikea.com/us/en/p/kallax-shelf-unit-white-20631663/", # ビジュアルスクレイピングするIKEA製品ページのURL
    "format": "raw",
    "country": "us",
    "data_format": "screenshot" # ウェブページのスクリーンショットを取得する
}

# アンロックされたターゲットページのスクリーンショットを取得する
web_unlocker_response = requests.post(
    "https://api.brightdata.com/request",
    json=payload,
    headers=headers
)

page_screenshot = web_unlocker_response.content

重要な変更はdata_formatフィールドで、"screenshot"に設定されています。これはWeb Unlockerにページスクリーンショットを返すよう指示します。APIレスポンスはPNG形式のスクリーンショット画像データで構成され、完全にレンダリングされたページを表します。

スクリーンショットをディスクにエクスポートします:

with open("screenshot.png", "wb") as f:
    f.write(page_screenshot)

このオプションのステップは、取得したページの視覚的な検査や抽出ワークフローのトラブルシューティングに役立ちます。

出力はscreenshot.pngファイルになります:

Web Unlocker APIが生成したIKEA製品ページのスクリーンショットを含む「screenshot.png」ファイル

Bright DataのWeb Unlocker APIがIKEA製品ページのフルスクリーンショットをキャプチャしたことに注目してください。次に進みましょう!

ステップ#2:Pydanticモデルを更新する

ページスクリーンショットの分析を通じて、GLM-5.3-FlashはページのMarkdown表現では利用できないビジュアル情報を識別できます。例えば、視覚的なラベルに埋め込まれたテキスト(「ベストセラー」タグなど)を解釈できます:

「ベストセラー」ビジュアルラベルに注目

同時に、スクリーンショットはすべてのページ情報を提供するわけではありません。例えば、Markdownベースの抽出ワークフローでアクセス可能だったimagesassembly_instructions_urlなどのフィールドは、ビジュアルデータからは取得できません。

それに応じて、ビジュアル処理用にIkeaProduct Pydanticモデルを調整します:

class IkeaProduct(BaseModel):
    title: Optional[str] = Field(None, description="IKEAウェブサイトに表示される製品の完全なタイトル")
    product_type: Optional[str] = Field(None, description="製品の一般的なタイプ(アームチェア、シェルフユニット、キャビネット、テーブルなど)")
    price: Optional[float] = Field(None, description="現在表示されている数値価格")
    currency: Optional[str] = Field(None, description="表示価格に使用される通貨(USDなど)")
    is_best_seller: Optional[bool] = Field(False, description="ベストセラーまたはトップセラーバッジが表示されているかどうか")
    badge_label: Optional[str] = Field(None, description="ページに表示されているプロモーションまたは製品バッジ(トップセラーなど)")
    delivery_options: Optional[List[str]] = Field(None, description="ページに表示されている配送または受け取りオプション")
    color: Optional[str] = Field(None, description="選択された製品の色または仕上げ(ホワイトやバーチ突板など)")
    visual_aspects: Optional[str] = Field(None, description="製品画像で視覚的に確認できる物理的特性の説明(形状、コンポーネント、仕上げ、構成など)")
    dimensions: Optional[str] = Field(None, description="IKEAウェブサイトに表示される製品全体の寸法")
    rating: Optional[float] = Field(None, description="平均顧客評価(通常5点満点)")
    review_count: Optional[int] = Field(None, description="表示されている顧客レビューの総数")

visual_aspectsフィールドの導入に注目してください。このフィールドはGLMに製品画像内で視覚的に確認できる物理的特性を記録するよう指示し、テキストベースのパースでは利用できない情報の抽出を可能にします。また、新しいis_best_sellerbadge_labelフィールドにも注目してください。

素晴らしい!更新されたPydanticモデルとウェブページのスクリーンショットをZ.ai APIに送信して、GLM-5.3-Flashによるビジュアルウェブスクレイピングを実行しましょう。

ステップ#3:GLM-5.3 Visionで画像からデータをスクレイピングする

ビジョン機能を持つOpenAIモデルと同様に、GLM-5.3-Flashはimage_urlフィールドを通じて画像を受け取ります。これは公開アクセス可能な画像URLまたはBase64エンコードされた画像表現を受け付けます。

スクリーンショットは画像バイトとしてローカルに存在するため、Base64としてエンコードする必要があります。そのためにPythonのbase64モジュールを使用します:

import base64
    
screenshot_base64 = base64.b64encode(page_screenshot).decode("utf-8")

次に、Base64エンコードされたスクリーンショットを抽出指示とともにGLM-5.3-Flashに送信します:

# GLM-5.3-Flashでビジュアルウェブデータパースを実行する
response = glm_client.chat.completions.create(
    model="glm-5.3-flash",
    messages=[
        {
            "role": "user",
            "content": [
                {
                    "type": "image_url",
                    "image_url": {
                        "url": f"data:image/png;base64,{screenshot_base64}"
                    },
                },
                {
                    "type": "text",
                    "text": f"""
提供されたウェブページのスクリーンショットからIKEA製品情報を抽出し、
提供されたJSONスキーマに準拠した構造化データとして返してください。

SCHEMA:
{json.dumps(IkeaProduct.model_json_schema(), indent=2)}
""",
                },
            ],
        }
    ],
    response_format={"type": "json_object"},
)

# 定義されたスキーマ形式でパースされたデータを取得する
product_data = response.choices[0].message.content

Z.ai APIへのリクエストは2つのコンポーネントで構成されます:

  1. ページスクリーンショット画像。
  2. 指定されたPydanticスキーマを使用して製品情報を取得するようGLM-5.3に指示するテキスト指示。

注意:今回のターゲットモデルは以前のglm-5.3ではなくglm-5.3-flashです。GLM-5.3はビジョン機能を持たないため、この変更が必要です。

結果はビジュアルスクレイピングされたデータを含むJSON文字列を格納したproduct_data変数です。前述のとおりディスクに保存します。印象的ですね!

ステップ#4:ビジュアルベースのGLMスクレイピングスクリプトをテストする

ビジュアルGLMウェブスクレイピングスクリプトの最終コードは以下のとおりです:

# pip install dotenv requests openai pydantic

from dotenv import load_dotenv
import os
import requests
import base64
import json
from pydantic import BaseModel, Field
from typing import List, Optional
from openai import OpenAI

# .envファイルから環境変数を読み込む
load_dotenv()

# 環境変数から必要なシークレットを読み込む
BRIGHT_DATA_API_KEY = os.environ.get("BRIGHT_DATA_API_KEY")
ZAI_API_KEY = os.environ.get("ZAI_API_KEY")

class IkeaProduct(BaseModel):
    title: Optional[str] = Field(None, description="IKEAウェブサイトに表示される製品の完全なタイトル")
    product_type: Optional[str] = Field(None, description="製品の一般的なタイプ(アームチェア、シェルフユニット、キャビネット、テーブルなど)")
    price: Optional[float] = Field(None, description="現在表示されている数値価格")
    currency: Optional[str] = Field(None, description="表示価格に使用される通貨(USDなど)")
    is_best_seller: Optional[bool] = Field(False, description="ベストセラーまたはトップセラーバッジが表示されているかどうか")
    badge_label: Optional[str] = Field(None, description="ページに表示されているプロモーションまたは製品バッジ(トップセラーなど)")
    delivery_options: Optional[List[str]] = Field(None, description="ページに表示されている配送または受け取りオプション")
    color: Optional[str] = Field(None, description="選択された製品の色または仕上げ(ホワイトやバーチ突板など)")
    visual_aspects: Optional[str] = Field(None, description="製品画像で視覚的に確認できる物理的特性の説明(形状、コンポーネント、仕上げ、構成など)")
    dimensions: Optional[str] = Field(None, description="IKEAウェブサイトに表示される製品全体の寸法")
    rating: Optional[float] = Field(None, description="平均顧客評価(通常5点満点)")
    review_count: Optional[int] = Field(None, description="表示されている顧客レビューの総数")

# Web Unlockerの認証ヘッダーを設定する
headers = {
    "Content-Type": "application/json",
    "Authorization": f"Bearer {BRIGHT_DATA_API_KEY}"
}

# Web Unlocker API呼び出しのリクエストペイロードを定義する
payload = {
    "zone": "web_unlocker", # Web UnlockerゾーンNameに置き換える
    "url": "https://www.ikea.com/us/en/p/kallax-shelf-unit-white-20631663/", # ビジュアルスクレイピングするIKEA製品ページのURL
    "format": "raw",
    "country": "us",
    "data_format": "screenshot" # ウェブページのスクリーンショットを取得する
}

# アンロックされたターゲットページのスクリーンショットを取得する
web_unlocker_response = requests.post(
    "https://api.brightdata.com/request",
    json=payload,
    headers=headers
)

page_screenshot = web_unlocker_response.content

# スクリーンショットをPNGファイルにエクスポートする
with open("screenshot.png", "wb") as f:
    f.write(page_screenshot)

# ビジョン処理のためにスクリーンショットをBase64に変換する
screenshot_base64 = base64.b64encode(page_screenshot).decode("utf-8")

# Z.ai用のOpenAI互換クライアントを初期化する
glm_client = OpenAI(
    api_key=ZAI_API_KEY,
    base_url="https://api.z.ai/api/paas/v4/",
)

# GLM-5.3-Flashでビジュアルウェブデータパースを実行する
response = glm_client.chat.completions.create(
    model="glm-5.3-flash",
    messages=[
        {
            "role": "user",
            "content": [
                {
                    "type": "image_url",
                    "image_url": {
                        "url": f"data:image/png;base64,{screenshot_base64}"
                    },
                },
                {
                    "type": "text",
                    "text": f"""
提供されたウェブページのスクリーンショットからIKEA製品情報を抽出し、
提供されたJSONスキーマに準拠した構造化データとして返してください。

SCHEMA:
{json.dumps(IkeaProduct.model_json_schema(), indent=2)}
""",
                },
            ],
        }
    ],
    response_format={"type": "json_object"},
)

# 定義されたスキーマ形式でパースされたデータを取得する
product_data = response.choices[0].message.content

# JSON文字列を検証済みのIkeaProductオブジェクトに変換する
product = IkeaProduct.model_validate_json(product_data)

# IkeaProductオブジェクトをJSONファイルにエクスポートする
with open("visual_product.json", "w", encoding="utf-8") as f:
    f.write(product.model_dump_json(indent=2))

スクリプトを起動すると、以下を含むvisual_product.jsonファイルが生成されます:

GLM-5.3-Flashでビジュアルスクレイピングされたデータを含む「visual_product.json」ファイル

「ベストセラー」ラベルを含む視覚的な側面を含む、ページスクリーンショットからの製品情報の取得成功に注目してください。素晴らしい!

まとめ

このチュートリアルでは、GLM-5.3とGLM-5.3-Flashを使用してLLM搭載ウェブデータ抽出システムを構築する方法を学びました。AIウェブスクレイピングの主な課題(ブロックされずにウェブコンテンツにアクセスし、LLM対応形式に変換すること)は、Bright DataのWeb Unlocker APIで簡単に解決されました。

ここで示したように、GLM-5.3とGLM-5.3-FlashをWeb Unlocker APIと組み合わせることで、ウェブページとそのビジュアル表現の両方から構造化情報を抽出できます。これはBright DataのAI互換ウェブアクセスソリューションがサポートする多くのユースケースの一つに過ぎません。

今すぐBright Dataに登録して、ウェブスクレイピングAPIを無料でお試しください!