ステップバイステップガイド:LLMパワードウェブスクレイパーの構築

LLM動力Webスクレイパーを構築する方法を知りたいですか?この記事を読んで手順を学びましょう!

Anakin AIを無料で利用開始

ステップバイステップガイド:LLMパワードウェブスクレイパーの構築

Start for free
目次

ウェブスクレイピングは、データ収集と分析における重要なツールとなっています。Large Language Models(LLMs)の登場により、より知能的で適応性のあるウェブスクレイパーを作成することができるようになりました。この記事では、従来のスクレイピング技術と言語モデルの力を組み合わせた、LLMを活用したウェブスクレイパーの構築プロセスについて説明します。

💡
制限なしでClaude 3.5 Sonnetを試してみたいですか?

すべてのAIモデルにアクセスできる、オールインワンの価格タグを持つAIプラットフォームをお探しですか?

それなら、Anakin AIを見逃せません!

Anakin AIは、ノーコードのアプリビルダーで強力なAIアプリを作成するためのオールインワンプラットフォームで、Llama 3ClaudeGPT-4Uncensored LLMsStable Diffusionなどとも簡単に統合できます...

Anakin AIで数分で夢のAIアプリを構築しましょう!

LLMウェブスクレイパーの紹介

LLMウェブスクレイパーは、従来のスクレイパーよりも効果的にWebページから情報を理解し抽出するために、大規模な言語モデルの機能を活用しています。これらのスクレイパーは、ウェブサイトの構造の変更に適応したり、コンテキストを理解したり、ルールベースのスクレイパーでは困難な暗黙の情報を抽出することさえも可能です。

前提条件

操作を開始する前に、次の項目がインストールされていることを確認してください。

  • Python 3.7+
  • pip(Pythonパッケージマネージャー)

ステップ1:環境のセットアップ

まず、仮想環境を作成し、必要なライブラリをインストールしましょう。

python -m venv llm_scraper_env
source llm_scraper_env/bin/activate  # Windowsの場合はこれを使用します: llm_scraper_env\Scripts\activate

pip install requests beautifulsoup4 langchain openai

ステップ2:基本的なウェブスクレイピングの準備

requestsとBeautifulSoupを使用して基本的なウェブスクレイピングのセットアップを始めましょう。

import requests
from bs4 import BeautifulSoup

def fetch_webpage(url):
    response = requests.get(url)
    if response.status_code == 200:
        return response.text
    else:
        raise Exception(f"ウェブページの取得に失敗しました。ステータスコード:{response.status_code}")

def parse_html(html_content):
    return BeautifulSoup(html_content, 'html.parser')

# 使い方の例
url = "https://example.com"
html_content = fetch_webpage(url)
soup = parse_html(html_content)

# 基本的な抽出
title = soup.title.string if soup.title else "タイトルが見つかりません"
paragraphs = [p.text for p in soup.find_all('p')]

print(f"タイトル:{title}")
print(f"段落の数:{len(paragraphs)}")

この基本的なセットアップでは、ウェブページを取得し、そのHTMLコンテンツを解析します。ただし、異なるウェブページ構造や複雑な情報の抽出に適応するための知能はありません。

ステップ3:LLMの統合

次に、LLMを統合してスクレイパーの機能を向上させましょう。LangChainライブラリを介してOpenAIのGPTモデルを使用します。

import os
from langchain.llms import OpenAI
from langchain.prompts import PromptTemplate
from langchain.chains import LLMChain

# OpenAI APIキーを設定します
os.environ["OPENAI_API_KEY"] = "ここにあなたのAPIキーを入力してください"

def create_llm_chain():
    llm = OpenAI(temperature=0.7)
    prompt_template = PromptTemplate(
        input_variables=["html_content", "extraction_task"],
        template="以下のHTMLコンテンツが与えられた場合:\n{html_content}\n\n次の情報を抽出してください:{extraction_task}"
    )
    return LLMChain(llm=llm, prompt=prompt_template)

llm_chain = create_llm_chain()

def extract_with_llm(html_content, extraction_task):
    return llm_chain.run(html_content=html_content, extraction_task=extraction_task)

# 使い方の例
extraction_task = "1. メインの見出し\n2. すべての製品名の一覧\n3. 各製品の価格"
result = extract_with_llm(html_content, extraction_task)
print(result)

このセットアップでは、LLMを使用してHTMLコンテンツを解釈し、与えられたタスクに基づいて特定の情報を抽出します。

ステップ4:HTMLクリーニングによる抽出の向上

LLMのパフォーマンスを向上させるために、モデルに渡す前にHTMLをクリーニングしてみましょう。

import re

def clean_html(html_content):
    # スクリプトとスタイルの要素を削除します
    soup = BeautifulSoup(html_content, 'html.parser')
    for script in soup(["script", "style"]):
        script.decompose()
    
    # テキストコンテンツを取得します
    text = soup.get_text()
    
    # 行ごとに分割し、各行の先頭と末尾のスペースを削除します
    lines = (line.strip() for line in text.splitlines())
    
    # 複数の見出しを1行ずつに分割します
    chunks = (phrase.strip() for line in lines for phrase in line.split("  "))
    
    # 空白行を削除します
    text = '\n'.join(chunk for chunk in chunks if chunk)
    
    return text

# extract_with_llm関数を修正します
def extract_with_llm(html_content, extraction_task):
    cleaned_content = clean_html(html_content)
    return llm_chain.run(html_content=cleaned_content, extraction_task=extraction_task)

このクリーニングプロセスにより、不要なHTML要素や書式を削除し、LLMが関連するコンテンツに集中しやすくなります。

ステップ5:アダプティブスクレイピングの実装

LLMの最大の利点の1つは、異なるウェブページ構造に適応できる能力です。異なるレイアウトを持つ複数のページをスクレイピングするための関数を実装しましょう。

def adaptive_scrape(urls, extraction_task):
    results = []
    for url in urls:
        try:
            html_content = fetch_webpage(url)
            extracted_info = extract_with_llm(html_content, extraction_task)
            results.append({"url": url, "extracted_info": extracted_info})
        except Exception as e:
            print(f"{url}のスクレイピングエラー:{str(e)}")
    return results

# 使い方の例
urls = [
    "https://example.com/product1",
    "https://example.com/product2",
    "https://anothersite.com/item"
]
extraction_task = "製品名、価格、簡単な説明を抽出する"
scraping_results = adaptive_scrape(urls, extraction_task)

for result in scraping_results:
    print(f"URL:{result['url']}")
    print(f"抽出された情報:\n{result['extracted_info']}\n")

このアダプティブスクレイピング関数は、異なる構造を持つ複数のURLを、すべてに共通の抽出タスクを使用して処理することができます。

ステップ6:構造化データの抽出の実装

自由形式のテキスト抽出は強力ですが、時には構造化データが必要な場合もあります。LLMチェーンを変更して出力をJSON形式にする方法を見てみましょう。

import json

def create_structured_llm_chain():
    llm = OpenAI(temperature=0.7)
    prompt_template = PromptTemplate(
        input_variables=["html_content", "extraction_task"],
        template="以下のHTMLコンテンツが与えられた場合:\n{html_content}\n\n次の情報を抽出してください:{extraction_task}\n\n結果を有効なJSONオブジェクトとして出力してください。"
    )
    return LLMChain(llm=llm, prompt=prompt_template)

structured_llm_chain = create_structured_llm_chain()

def extract_structured_data(html_content, extraction_task):
    cleaned_content = clean_html(html_content)
    result = structured_llm_chain.run(html_content=cleaned_content, extraction_task=extraction_task)
    try:
        return json.loads(result)
    except json.JSONDecodeError:
        print("LLMの出力をJSONとして解析できませんでした。生の出力:")
        print(result)
        return None

# 使い方の例
extraction_task = "product_name, price, description"
structured_data = extract_structured_data(html_content, extraction_task)
if structured_data:
    print(json.dumps(structured_data, indent=2))

この変更により、LLMの出力が構造化されたJSONデータとして出力されるため、抽出された情報を処理や保存に容易に利用できるようになります。

ステップ7:ページネーションと動的コンテンツの処理

多くのウェブサイトでは、ページネーションや動的なコンテンツを使用しています。このスクレイパーは、これらのシナリオに対応するように拡張します。

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

def fetch_dynamic_webpage(url, wait_for_element=None, scroll=False):
    options = webdriver.ChromeOptions()
    options.add_argument('--headless')
    driver = webdriver.Chrome(options=options)
    
    try:
        driver.get(url)
        
        if wait_for_element:
            WebDriverWait(driver, 10).until(
                EC.presence_of_element_located((By.CSS_SELECTOR, wait_for_element))
            )
        
        if scroll:
            # ページの最後までスクロールします
            driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
            # 遅延ロードされるコンテンツを待ちます
            import time
            time.sleep(2)
        
        return driver.page_source
    finally:
        driver.quit()

def scrape_paginated_content(base_url, num_pages, extraction_task):
    all_data = []
    for page in range(1, num_pages + 1):
        url = f"{base_url}?page={page}"
        html_content = fetch_dynamic_webpage(url, wait_for_element='.product-list', scroll=True)
        page_data = extract_structured_data(html_content, extraction_task)
        if page_data:
            all_data.extend(page_data)
    return all_data

# 使い方の例
base_url = "https://example.com/products"
num_pages = 3
extraction_task = "製品の配列を抽出し、各製品には:名前、価格、評価があります"
paginated_data = scrape_paginated_content(base_url, num_pages, extraction_task)
print(json.dumps(paginated_data, indent=2))

この拡張機能では、Seleniumを使用して動的なコンテンツとページネーションを処理し、より複雑なウェブサイトからデータを抽出します。

ステップ8:レート制限とエラーハンドリングの実装

責任あるスクレイピングのために、レート制限と頑健なエラーハンドリングを追加しましょう。

import time
from ratelimit import limits, sleep_and_retry

# @sleep_and_retryと@limitsデコレータを使用してレート制限を追加します(1回の呼び出しを5秒ごとに制限します)
@sleep_and_retry
@limits(calls=1, period=5)
def rate_limited_fetch(url):
    return fetch_webpage(url)

def scrape_with_retries(url, extraction_task, max_retries=3):
    for attempt in range(max_retries):
        try:
            html_content = rate_limited_fetch(url)
            return extract_structured_data(html_content, extraction_task)
        except Exception as e:
            print(f"試行{attempt + 1}でエラーが発生しました:{str(e)}")
            if attempt == max_retries - 1:
                print(f"{max_retries}回の試行で{url}のスクレイピングに失敗しました")
                return None
            time.sleep(5)  # リトライ前の待機時間

# 使い方の例
url = "https://example.com/product"
extraction_task = "product_name, price, availability"
result = scrape_with_retries(url, extraction_task)
if result:
    print(json.dumps(result, indent=2))

この実装により、対象のウェブサイトを過負荷にすることを防ぐためのレート制限が追加され、一時的なエラーを処理するためのリトライロジックが提供されます。

結論

LLMを活用したウェブスクレイパーの構築により、従来のウェブスクレイピング技術の柔軟性と大規模な言語モデルの知能を組み合わせることができます。この手法により、さまざまなウェブサイトの構造やコンテンツの種類に対応できるより適応性のあるデータ抽出を行うことができます。

このガイドに示された手順に従って、LLMを活用した強力なウェブスクレイピングツールを作成することができます。常にウェブサイトの利用規約を尊重し、適切なレート制限を実装するなど、責任を持ってスクレイピングを行うようにしてください。

LLMウェブスクレイパーをさらに発展させる際には、次のような高度な機能の探索を考えてみてください:

  1. 簡単なタスク定義のためのユーザーインターフェースの実装
  2. データベースへのスクレイプデータの保存
  3. 定期的で自動化されたスクレイピングタスクのパイプラインの作成
  4. 特定ドメインでのLLMのファインチューニングによる精度向上

これらの強化により、LLMウェブスクレイパーはさまざまな領域やアプリケーションでのデータ収集と分析に貴重なツールとなるでしょう。

💡
制限なしでClaude 3.5 Sonnetを試してみたいですか?

すべてのAIモデルにアクセスできる、オールインワンの価格タグを持つAIプラットフォームをお探しですか?

それなら、Anakin AIを見逃せません!

Anakin AIは、ノーコードのアプリビルダーで強力なAIアプリを作成するためのオールインワンプラットフォームで、Llama 3ClaudeGPT-4Uncensored LLMsStable Diffusionなどとも簡単に統合できます...

Anakin AIで数分で夢のAIアプリを構築しましょう!