AI

KimiによるWebスクレイピング:ステップバイステップガイド

Kimi K3とBright DataのWeb Unlockerを組み合わせてインテリジェントなウェブスクレイピングを実現。アクセス障壁を克服しながらAIでデータを抽出。
1 分読
Web Scraping with Kimi

この記事では、以下のことを学びます:

  • Kimi K3がLLMを活用したウェブスクレイピングに最適なモデルである理由。
  • AIを活用したウェブスクレイピングの主な障壁と、Bright Data Web Unlocker APIがその解決策である理由。
  • PythonスクリプトでKimiを使ってAI搭載のウェブスクレイピングを実行する方法。
  • Kimi K3をビジュアルウェブスクレイピングに活用する方法。

さっそく始めましょう!

ウェブスクレイピングにKimiを使う理由

LLMはウェブスクレイピングに新しいアプローチをもたらします。生のHTMLからデータを取得するために複雑なパースロジックを書く代わりに、AIモデルに抽出を任せることができます。これにより、スクレイパーは脆弱なCSSセレクターやXPath式に依存する必要がなくなります。

必要なのは、モデルに抽出すべきデータを伝えるよく設計されたプロンプトだけです。わずか数行のコードで、任意のウェブページから構造化データをスクレイピングするようKimiに指示できます。このAI搭載のアプローチにより、ウェブスクレイパーをより柔軟でメンテナンスしやすくできます。

最新のKimiモデルであるKimi K3は、テキストベースのデータ抽出に適しています。また、ウェブページのスクリーンショット、画像、その他のビジュアル要素から情報を抽出できるビジョン機能も提供しています。

詳細については、以下のガイドをご参照ください:

  1. ウェブスクレイピングへのAI活用
  2. ウェブスクレイピングへのビジョンAI活用

AIウェブスクレイピングの主な課題とその克服方法

AIを活用したウェブスクレイピングの最大の課題は、従来のウェブスクレイピングで直面するものとほぼ同じです。AIは柔軟な抽出機能によりページ構造の変更を問題にしにくくしますが、JavaScriptレンダリング、アンチボットシステム、フィンガープリンティング、レート制限、CAPTCHA、その他のアクセス制限への対処は依然として必要です。

結局のところ、AIスクレイピングはウェブページを大規模に取得する際の障壁を排除しません。LLMがページをパースする前に、スクレイパーはまずそのコンテンツを取得する必要があり、自動リクエストの成功を妨げるあらゆる対策への対処が求められます。

さらに、トークン使用量も重要です。大きなHTMLドキュメントをKimi K3のような強力なモデルに送信するとすぐにコストが高くなります。この場合の解決策は、生のHTMLをLLM最適化Markdownに変換することです。

ウェブページをクリーンなMarkdownに変換すると、関連するコンテンツと構造を保持しながら、生のHTMLと比較して不要なトークンを大幅に削減できます。見出し、リスト、リンク、その他のページ要素などの情報をLLMが処理しやすい形式で保持することもできます。ウェブサイトをMarkdownにスクレイピングする方法のチュートリアルをご参照ください。

Bright Data Web Unlocker API:解決策

Bright DataのWeb Unlocker APIは、AIを活用したウェブスクレイピングの主な課題に対する実用的な解決策を提供します。

このエンドポイントはウェブページのURLを受け取り、一般的なアンチボットおよびアンチスクレイピングメカニズムを処理しながらそのコンテンツを返します。CAPTCHAを解決し、JavaScriptが多用されたページをレンダリングし、ブラウザフィンガープリンティングの問題を克服し、レート制限を管理するなどの機能を備えています。

Web Unlockerは取得したコンテンツを以下を含む様々な形式で返すこともできます:

  1. LLM最適化Markdown
  2. スクリーンショット

Web Unlocker APIリクエストの出力は、Kimi K3によるテキストベースまたはビジュアル抽出のいずれかの入力として使用できます。

注意:Web Unlocker APIはBright Dataの無料プランに含まれており、毎月5,000件の無料リクエストが提供されます。

Web Unlocker APIが際立っている点は、4億以上のレジデンシャルIPを含む大規模なBright Dataのプロキシインフラ上で動作し、無制限の同時実行をサポートしていることです。これにより、プログラムによるウェブスクレイピングのための信頼性が高くスケーラブルな基盤が提供されます。

PythonでKimi K3を使ったウェブスクレイピングの実行方法

このガイドセクションでは、AIを活用したウェブスクレイピングにKimiを使用するPythonスクリプトの構築方法を学びます。対象ページはAmazonの商品ページです。

具体的には、「Amazon Basics 20-Pack AA Alkaline Batteries, 1.5 Volt, 10-Year Leak-Free Shelf Life, for Everyday and Household Devices」商品のスクレイピング方法を紹介します。ただし、このアプローチの利点は、構造やレイアウトに関わらず他のAmazon商品ページでも機能することです。

注意:本番環境向けの構造化されたAmazon商品データ取得には、Amazon Scraper APIの使用をご検討ください。

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

  1. Bright Data Web Unlocker APIが対象ページを取得し、Markdown形式でコンテンツを返します。
  2. Kimi K3がMarkdownコンテンツを受け取り、Kimi APIを通じて商品情報を収集します。
  3. 抽出されたデータは、事前定義されたスキーマに基づいて構造化JSONとして返されます。
  4. スクレイピングされた商品データがディスクに出力されます。

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

前提条件

始める前に、以下を準備してください:

ここでは、Web Unlocker APIゾーンの名前がweb_unlockerであると仮定します:

「web_unlocker」Web Unlocker APIに注目

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

まず、Kimiウェブスクレイピングプロジェクト用の新しいフォルダを作成します:

mkdir kimi-scraper

kimi-scraperディレクトリがKimiでのウェブスクレイピングのプロジェクトフォルダとして機能します。

フォルダに移動し、その中にPython仮想環境を作成します:

cd kimi-scraper
python -m venv .venv

Visual Studio CodeとPython拡張機能PyCharm Community Editionなど、お好みのPython IDEでプロジェクトフォルダを開きます。

プロジェクトフォルダにscraper.pyファイルを作成します:

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

scraper.pyには間もなくKimiを介したLLMウェブスクレイピングのPythonロジックが含まれます。

次に、ターミナルで仮想環境を有効化します。LinuxまたはmacOSの場合は以下を実行します:

source .venv/bin/activate

Windowsの場合は以下を実行します:

.venv\Scripts\activate

仮想環境を有効化した状態で、以下のコマンドですべてのプロジェクト依存関係をインストールします:

pip install dotenv requests openai pydantic

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

  • dotenv.envファイルからAPIシークレットを読み込むため。
  • requests:Bright Data Web Unlocker APIにウェブページ取得リクエストを送信するため。
  • openai:OpenAI互換のKimi APIに接続し、取得したウェブページを処理するため。
  • pydantic:ウェブスクレイピングKimiリクエストの出力モデルを定義するため。

完了です!Kimiでウェブスクレイピングを行うPythonプロジェクトが整いました。

ステップ#2:環境変数読み取りの設定

KimiウェブスクレイパーはBright DataやKimiを含むサードパーティサービスに接続します。これらのサービスは認証にAPIキーを使用しており、ソースコードにそのようなシークレットをハードコードすべきではありません。

代わりに、APIキーを環境ファイルに保存し、実行時に読み込みます。そのためにpython-dotenvパッケージを使用して.envファイルから環境変数を読み込みます。

scraper.pyload_dotenv()をインポートして呼び出します:

from dotenv import load_dotenv

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

次に、プロジェクトフォルダに.envファイルを追加します:

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

APIキーを記入します:

MOONSHOT_API_KEY="<YOUR_MOONSHOT_API_KEY>"
BRIGHT_DATA_API_KEY="<YOUR_BRIGHT_DATA_API_KEY>" 

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

  • <YOUR_MOONSHOT_API_KEY>をKimiのAPIキーに。
  • <YOUR_BRIGHT_DATA_API_KEY>をBright DataのAPIキーに。

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

import os

MOONSHOT_API_KEY = os.environ.get("MOONSHOT_API_KEY")
BRIGHT_DATA_API_KEY = os.environ.get("BRIGHT_DATA_API_KEY")

完了です!APIキーが公開されることなくスクレイパーで利用できるようになりました。

ヒント:バージョン管理リポジトリでは、APIキーが誤ってコミットされないよう.env.gitignoreファイルに追加してください。

ステップ#3:Web Unlocker APIで対象ウェブページを取得

Kimiを活用したスクレイピングスクリプトの最初のステップは、LLM最適化Markdown形式で対象ウェブページを取得することです。最も簡単な方法はBright Data Web Unlocker APIを使用することです。

Web Unlockerへの接続方法の詳細については、公式ドキュメントを参照するか、Bright DataリポジトリのPythonサンプルを確認してください。

requestsライブラリを使用してWeb Unlocker APIに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 API名に置き換えてください
    "url": "https://www.amazon.com/Amazon-Basics-Batteries-Leak-Free-Household/dp/B00NTCH52W/",
    "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 Requestsガイドをご参照ください。

リクエストペイロード内のdata_format="markdown"フィールドに注目してください。これはWeb Unlocker APIに対して、生のHTMLの代わりにウェブページをMarkdownとして返すよう指示します。

markdown_pageを出力すると、以下のようになります:

Amazon商品ページのMarkdown表現

これは対象のAmazon商品ページのMarkdown表現に対応しています。

ご覧のように、Web Unlockerはページ取得の困難な部分を以下のように処理します:

  1. Bright Dataのレジデンシャルプロキシインフラを通じて対象のAmazonページにアクセス。
  2. Amazon CAPTCHAを含む一般的なアンチボットの課題への対処。
  3. レンダリングされたページコンテンツの取得。
  4. ページをクリーンなMarkdownに変換して返却。

これでKimiにAI搭載のデータ抽出のために渡せる形式のページコンテンツが手に入りました。その前に、Kimiが生成する対象出力モデルを定義しましょう!

ステップ#4:出力データモデルの定義

Kimiは他のLLMと同様、デフォルトではテキストベースの応答を返します。これはウェブスクレイピングには理想的ではなく、通常は非構造化ウェブページコンテンツを構造化データに変換したいものです。

Kimi APIはJSONモードによる構造化出力をサポートしています。これにより、応答の構造を定義し、そのスキーマに準拠したデータを返すようモデルに指示できます。

PythonでJSONスキーマを定義する最も簡単な方法の一つは、データバリデーションとパースの人気ライブラリであるPydanticを使用することです。Pydanticを使用すると、Pythonクラスを使ってデータの期待される構造と型を定義でき、それをKimi API用のJSONスキーマオブジェクトに変換できます。

まず、対象ページを確認して収集したいフィールドを特定します。このチュートリアルで使用するAmazon商品ページでは、以下のようにPydanticモデルを定義できます:

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

class Product(BaseModel):
    asin: Optional[str] = Field(None, description="The Amazon Standard Identification Number (e.g., B00NTCH52W)")
    title: Optional[str] = Field(None, description="The full product title")
    brand: Optional[str] = Field(None, description="Brand name (e.g., Amazon Basics)")
    price: Optional[float] = Field(None, description="One-time purchase price")
    rating: Optional[float] = Field(None, description="Average customer rating out of 5")
    review_count: Optional[int] = Field(None, description="Total number of customer reviews")
    size_options: Optional[List[str]] = Field(None, description="Available pack sizes or variants")
    about_item: Optional[List[str]] = Field(None, description="Bullet points under 'About this item'")
    images: Optional[List[str]] = Field(None, description="URLs for product images")
    category_path: Optional[List[str]] = Field(None, description="Breadcrumb navigation list")
    is_in_stock: Optional[bool] = Field(True, description="Availability status")

このモデルはAmazon商品ページの最も関連性の高いフィールドを型付きPythonフィールドにマッピングします。Kimi K3はページコンテンツから対応する値を取得し、予測可能なJSONスキーマで返します。

完了です!Kimiをウェブスクレイピングに使用するために必要なものがすべて揃いました。

ステップ#5:Kimiをデータパースに使用

Kimi APIはOpenAI互換であるため、OpenAI Python SDKを使用してアクセスできます。KimiのAPIキー(MOONSHOT_API_KEY環境変数)とMoonshotのAPIベースURLでOpenAIクライアントを設定するだけです。

次に、Chat Completions APIを使用してスクレイピングされたMarkdownコンテンツをKimi K3に送信し、PydanticスキーマにしたがってProduct情報を抽出します:

from openai import OpenAI

# KimiのOpenAIクライアントを初期化
kimi_client = OpenAI(
    api_key=MOONSHOT_API_KEY,
    base_url="https://api.moonshot.ai/v1",
)

# Kimiでウェブデータパースを実行
response = kimi_client.chat.completions.create(
    model="kimi-k3",
    messages=[
        {
            "role": "user",
            "content": [
                {
                    "type": "text",
                    "text":
                        f"""
                        Extract the product information from the following Markdown document
                        and return it according to the provided schema.

                        MARKDOWN:
                        {markdown_page}
                        """,
                },
            ],
        }
    ],
    response_format={
        "type": "json_schema",
        "json_schema": {
            "name": "product",
            "strict": True,
            "schema": Product.model_json_schema(), # PydanticスキーマをJSONスキーマオブジェクトに変換
        },
    },
)

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

ユーザープロンプトにはBright DataのWeb Unlocker APIで取得したMarkdownページが含まれており、関連する商品情報を返すようKimiに指示しています。

response_formatパラメーターはjson_schemaモードを有効にします。ここで、Product.model_json_schema()はPydanticモデルをKimiが応答の構造化に使用するJSONスキーマに変換します。

その結果、product_dataにはProductモデルで定義された構造の抽出済み商品データを含むJSON文字列が格納されます。このJSON文字列をPythonオブジェクトにパースし、最終ステップとして構造化データをディスクに保存します!

ステップ#6:スクレイピングデータのエクスポート

スクレイピングされた商品データをJSONファイルとして保存します:

import json

with open("product.json", "w", encoding="utf-8") as f:
    json.dump(json.loads(product_data), f, indent=2, ensure_ascii=False)

注意json.dump(json.loads(...))はKimiが出力するデータが有効なJSONであることを保証します。

これにより、ProductのPydanticスキーマに従ってKimiで収集された構造化商品データを含むproduct.jsonファイルが作成されます。完璧です!

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

以下がKimiスクレイパーの最終コードです:

# 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()

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

# 商品情報の出力スキーマ
class Product(BaseModel):
    asin: Optional[str] = Field(None, description="The Amazon Standard Identification Number (e.g., B00NTCH52W)")
    title: Optional[str] = Field(None, description="The full product title")
    brand: Optional[str] = Field(None, description="Brand name (e.g., Amazon Basics)")
    price: Optional[float] = Field(None, description="One-time purchase price")
    rating: Optional[float] = Field(None, description="Average customer rating out of 5")
    review_count: Optional[int] = Field(None, description="Total number of customer reviews")
    size_options: Optional[List[str]] = Field(None, description="Available pack sizes or variants")
    about_item: Optional[List[str]] = Field(None, description="Bullet points under 'About this item'")
    images: Optional[List[str]] = Field(None, description="URLs for product images")
    category_path: Optional[List[str]] = Field(None, description="Breadcrumb navigation list")
    is_in_stock: Optional[bool] = Field(True, description="Availability status")

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

# Web Unlocker APIコールのリクエストペイロードを定義
payload = {
    "zone": "web_unlocker", # Web Unlocker API名に置き換えてください
    "url": "https://www.amazon.com/Amazon-Basics-Batteries-Leak-Free-Household/dp/B00NTCH52W/",
    "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

# KimiのOpenAIクライアントを初期化
kimi_client = OpenAI(
    api_key=MOONSHOT_API_KEY,
    base_url="https://api.moonshot.ai/v1",
)

# Kimiでウェブデータパースを実行
response = kimi_client.chat.completions.create(
    model="kimi-k3",
    messages=[
        {
            "role": "user",
            "content": [
                {
                    "type": "text",
                    "text":
                        f"""
                        Extract the product information from the following Markdown document
                        and return it according to the provided schema.

                        MARKDOWN:
                        {markdown_page}
                        """,
                },
            ],
        }
    ],
    response_format={
        "type": "json_schema",
        "json_schema": {
            "name": "product",
            "strict": True,
            "schema": Product.model_json_schema(), # PydanticスキーマをJSONスキーマオブジェクトに変換
        },
    },
)

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

# スクレイピングされたデータをJSONファイルにエクスポート
with open("product.json", "w", encoding="utf-8") as f:
    json.dump(json.loads(product_data), f, indent=2, ensure_ascii=False)

以下のコマンドでPythonスクリプトを実行します:

python scraper.py

Web Unlocker APIでページを取得してからKimi LLMで処理するまでの実行には時間がかかります。しばらくお待ちください。

結果はKimiが返したスクレイピング済み商品データを含むproduct.jsonファイルになります:

Kimiが返したスクレイピング済みデータ

抽出されたデータが対象のAmazon商品ページで利用可能な情報と密接に一致していることに注目してください:

対象のAmazon商品ページ

Web Unlocker APIはAmazonのアンチボット対策を処理してLLM最適化Markdownページコンテンツを取得し、Kimi K3はそのコンテンツを正常にパースして構造化データに変換しました。ミッション完了!

Kimi K3ビジョン機能でビジュアルウェブスクレイピングを実行する方法

Kimi K3はビジョンモデルでもあり、ビジュアルウェブスクレイピングを実行できます。LLMにウェブページのテキストコンテンツを提供する代わりに、スクリーンショットや画像を提供してKimi K3に構造化データを抽出させることができます。

アプローチはシンプルです:

  1. Bright Data Web Unlocker APIが対象ウェブページ(前回と同じAmazon商品ページ)のスクリーンショットを取得します。
  2. Kimi K3がKimi APIを通じてスクリーンショットを受け取り、事前定義されたスキーマに従って商品情報を収集します。
  3. スクレイピングされたデータが構造化JSONとしてディスクに保存されます。

注意:ワークフローの大部分は変わらないため、このセクションではビジュアルウェブスクレイピングのために更新が必要なステップのみを説明します。前述の前提条件とセットアップ手順はすべて引き続き適用されます。

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

Web Unlocker APIリクエストを更新して、Markdown形式のページコンテンツの代わりにスクリーンショットを返すようにします:

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

# Web Unlocker APIコールのリクエストペイロードを定義
payload = {
    "zone": "web_unlocker", # Web Unlocker API名に置き換えてください
    "url": "https://www.amazon.com/Amazon-Basics-Batteries-Leak-Free-Household/dp/B00NTCH52W/",
    "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にスクリーンショットを返すよう指示します。特に、APIレスポンスにはフルレンダリングされたページを表すPNG画像バイトとしてスクリーンショットが含まれます。

ビジュアルデバッグのために、スクリーンショットをディスクにエクスポートします:

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

これはオプションですが、取得したページを視覚的に確認してKimiスクレイピングワークフローのトラブルシューティングに役立ちます。

結果はscreenshot.pngファイルです:

Bright Data Web Unlocker APIが生成した「screenshot.png」ファイル

これにはBright Data Web Unlocker APIによってキャプチャされたAmazon商品ページ全体のスクリーンショットが含まれています。さあ始めましょう!

ステップ#2:Pydanticモデルの更新

対象ページのスクリーンショットを分析することで、Kimi K3はページのMarkdownコンテンツでは利用できないビジュアル情報を取得できます。例えば、「メーカーより」セクションのテキストなど、画像に埋め込まれたテキストを読み取ることができます:

対象のAmazon商品ページの「メーカーより」セクション

同時に、スクリーンショットは基礎となる画像URLを提供しません。そのため、以前のテキストベースのKimi K3スクレイピングワークフローで利用可能だったimagesなどのフィールドは入力できません。

したがって、ProductのPydanticモデルを以下のように適応させます:

class Product(BaseModel):
    asin: Optional[str] = Field(None, description="The Amazon Standard Identification Number (e.g., B00NTCH52W)")
    title: Optional[str] = Field(None, description="The full product title")
    brand: Optional[str] = Field(None, description="Brand name (e.g., Amazon Basics)")
    price: Optional[float] = Field(None, description="One-time purchase price")
    rating: Optional[float] = Field(None, description="Average customer rating out of 5")
    review_count: Optional[int] = Field(None, description="Total number of customer reviews")
    size_options: Optional[List[str]] = Field(None, description="Available pack sizes or variants")
    from_the_manufacturer_info: Optional[str] = Field(None, description="Text of the image in the 'From the manufacturer' section")
    category_path: Optional[List[str]] = Field(None, description="Breadcrumb navigation list")
    is_in_stock: Optional[bool] = Field(True, description="Availability status")

新しいfrom_the_manufacturer_infoフィールドに注目してください。これは商品ページの「メーカーより」セクションの画像内に表示されているテキストを読み取って抽出するようKimiに明示的に指示します。

素晴らしい!新しいPydanticモデルとウェブページのスクリーンショットをKimi APIに渡してウェブスクレイピングを行います。

ステップ#3:Kimi K3ビジョンで画像からデータをスクレイピング

Kimiはimage_urlタイプを通じて画像を受け取ります。このタイプは公開アクセス可能な画像URLまたはBase64エンコードされた画像表現をサポートしています。

スクリーンショットは画像バイトとしてローカルに保存されているため、まずBase64としてエンコードする必要があります。Python標準ライブラリのbase64パッケージを使用してこれを実現します:

import base64

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

次に、エンコードされたスクリーンショットを抽出プロンプトとともにKimi K3に渡すことができます:

response = kimi_client.chat.completions.create(
    model="kimi-k3",
    messages=[
        {
            "role": "user",
            "content": [
                {
                    "type": "image_url",
                    "image_url": {
                        "url": (
                            f"data:image/png;base64,{screenshot_base64}"
                        ),
                    },
                },
                {
                    "type": "text",
                    "text":
                        """
                        Extract the product information from this Amazon product page screenshot.
                        Return the information according to the provided schema.
                        """,
                },
            ],
        }
    ],
    response_format={
        "type": "json_schema",
        "json_schema": {
            "name": "product",
            "strict": True,
            "schema": Product.model_json_schema(), # PydanticスキーマをJSONスキーマオブジェクトに変換
        },
    },
)

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

リクエストには2つの情報が含まれています:

  1. ページのスクリーンショット。
  2. 指定されたPydanticスキーマを使用して商品情報を抽出するようKimiに指示するテキストプロンプト。

結果は視覚的にスクレイピングされた商品情報を含むJSON文字列が格納されたproduct_data変数です。前のセクションで説明したのと同じ方法でディスクに保存できます。以上です!

ステップ#4:ビジュアルAIスクレイパーのテスト

ビジュアルウェブスクレイピングKimiスクリプトには以下が含まれます:

# pip install dotenv requests openai pydantic

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

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

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

# 商品情報の出力スキーマ
class Product(BaseModel):
    asin: Optional[str] = Field(None, description="The Amazon Standard Identification Number (e.g., B00NTCH52W)")
    title: Optional[str] = Field(None, description="The full product title")
    brand: Optional[str] = Field(None, description="Brand name (e.g., Amazon Basics)")
    price: Optional[float] = Field(None, description="One-time purchase price")
    rating: Optional[float] = Field(None, description="Average customer rating out of 5")
    review_count: Optional[int] = Field(None, description="Total number of customer reviews")
    size_options: Optional[List[str]] = Field(None, description="Available pack sizes or variants")
    from_the_manufacturer_info: Optional[str] = Field(None, description="Text of the image in the 'From the manufacturer' section")
    category_path: Optional[List[str]] = Field(None, description="Breadcrumb navigation list")
    is_in_stock: Optional[bool] = Field(True, description="Availability status")

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

# Web Unlocker APIコールのリクエストペイロードを定義
payload = {
    "zone": "web_unlocker", # Web Unlockerゾーン名に置き換えてください
    "url": "https://www.amazon.com/Amazon-Basics-Batteries-Leak-Free-Household/dp/B00NTCH52W/",
    "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)

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

# KimiのOpenAIクライアントを初期化
kimi_client = OpenAI(
    api_key=MOONSHOT_API_KEY,
    base_url="https://api.moonshot.ai/v1",
)

# Kimiでビジュアルウェブデータパースを実行
response = kimi_client.chat.completions.create(
    model="kimi-k3",
    messages=[
        {
            "role": "user",
            "content": [
                {
                    "type": "image_url",
                    "image_url": {
                        "url": (
                            f"data:image/png;base64,{screenshot_base64}"
                        ),
                    },
                },
                {
                    "type": "text",
                    "text":
                        """
                        Extract the product information from this Amazon product page screenshot.
                        Return the information according to the provided schema.
                        """,
                },
            ],
        }
    ],
    response_format={
        "type": "json_schema",
        "json_schema": {
            "name": "product",
            "strict": True,
            "schema": Product.model_json_schema(), # PydanticスキーマをJSONスキーマオブジェクトに変換
        },
    },
)

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

# スクレイピングされたデータをJSONファイルにエクスポート
with open("image_product.json", "w", encoding="utf-8") as f:
    json.dump(json.loads(product_data), f, indent=2, ensure_ascii=False)

起動すると、以下のようなimage_product.jsonファイルが生成されます:

Kimiが返したビジュアルスクレイピング済みデータ

Kimi K3が「メーカーより」画像に埋め込まれたテキストを含む商品データをスクリーンショットから取得した様子をご覧ください。素晴らしい!

まとめ

このブログ記事では、Kimi K3を使用してAI搭載のウェブスクレイパーを構築する方法を学びました。ウェブコンテンツを確実に取得してブロックされることなくLLM最適化データを取得するという最大の課題は、Bright DataのWeb Unlocker APIで対処しました。

説明したように、Kimi K3とWeb Unlocker APIを組み合わせることで、カスタムパースロジックを書くことなく、シンプルなプロンプトを使用してウェブページやページのスクリーンショットから構造化データを抽出できます。これはBright DataのAI対応サービスがサポートする多くのユースケースの一つに過ぎません。

Bright Dataに登録して、ウェブスクレイピングAPIを無料で試してみましょう!