← ブログ一覧に戻る
業務自動化

Cursor/Claude CodeでPythonスクレイピングコードを生成・改善する実践ガイド

#Cursor#Claude Code#Python#スクレイピング#コード生成#コーディングエージェント

はじめに

Pythonでスクレイピングコードを書く際、最初から完璧なコードを書くのは難しいものです。HTMLの構造を理解し、適切な待機処理を実装し、エラーハンドリングを組み込む——これらすべてを手動で実装するのは時間がかかります。

CursorClaude Codeなどのコーディングエージェントを活用することで、スクレイピングコードの開発を大幅に効率化できます。この記事では、実際のプロジェクトで活用した経験を基に、コーディングエージェントを使った効率的な開発方法を解説します。

コーディングエージェントとは

コーディングエージェントは、AIを活用してコードの生成、補完、改善を支援するツールです。

  • Cursor: AI統合型のコードエディタ。コード生成、リファクタリング、バグ修正を支援
  • Claude Code: AnthropicのClaudeを活用したコード生成・改善ツール

これらのツールは、自然言語での指示(プロンプト)からコードを生成したり、既存のコードを改善したりできます。

実践例1:基本的なスクレイピングコードの生成

プロンプト設計のポイント

コーディングエージェントに効果的に指示するには、具体的で構造化されたプロンプトが重要です。

良いプロンプト例:

Pythonでスクレイピングコードを作成してください。

要件:
- 対象URL: https://example.com/jobs
- 取得したい情報: タイトル、会社名、給与、勤務地
- リクエスト間隔: 1-3秒のランダム待機
- エラーハンドリング: リトライ3回まで
- 出力: CSV形式

使用ライブラリ: requests, BeautifulSoup, pandas

悪いプロンプト例:

スクレイピングコードを書いて

具体的な要件を明示することで、エージェントはより正確なコードを生成できます。

生成されたコードの改善

エージェントが生成したコードは、そのまま使うのではなく、必ずレビューと改善を行います。

# エージェントが生成したコード(改善前)
import requests
from bs4 import BeautifulSoup

def scrape_jobs():
    response = requests.get("https://example.com/jobs")
    soup = BeautifulSoup(response.text, "html.parser")
    jobs = soup.find_all("div", class_="job-item")
    return jobs

改善ポイント:

  1. User-Agentの設定: サイトによってはUser-Agentのチェックがある
  2. エラーハンドリング: ネットワークエラーやHTML解析エラーへの対応
  3. 待機処理: サーバーへの負荷を考慮したリクエスト間隔
# 改善後のコード
import requests
from bs4 import BeautifulSoup
import time
import random
from typing import List, Dict

def scrape_jobs(url: str, max_retries: int = 3) -> List[Dict]:
    """求人情報をスクレイピング"""
    headers = {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
    }
    
    for attempt in range(max_retries):
        try:
            time.sleep(random.uniform(1.0, 3.0))  # 1-3秒のランダム待機
            response = requests.get(url, headers=headers, timeout=10)
            response.raise_for_status()
            
            soup = BeautifulSoup(response.text, "html.parser")
            jobs = []
            
            for item in soup.find_all("div", class_="job-item"):
                job = {
                    "title": item.find("h2").get_text(strip=True) if item.find("h2") else "",
                    "company": item.find("span", class_="company").get_text(strip=True) if item.find("span", class_="company") else "",
                    "salary": item.find("span", class_="salary").get_text(strip=True) if item.find("span", class_="salary") else "",
                    "location": item.find("span", class_="location").get_text(strip=True) if item.find("span", class_="location") else "",
                }
                jobs.append(job)
            
            return jobs
            
        except requests.RequestException as e:
            if attempt < max_retries - 1:
                time.sleep(2 ** attempt)  # 指数バックオフ
                continue
            raise
    
    return []

実践例2:エラー修正の効率化

スクレイピングコードでよくあるエラーを、コーディングエージェントで効率的に修正する方法を紹介します。

エラー1:要素が見つからない

# エラーが発生するコード
title = soup.find("h2").get_text()  # AttributeError: 'NoneType' object has no attribute 'get_text'

Cursor/Claude Codeでの修正方法:

エラーメッセージとコードをエージェントに提示すると、安全なコードを提案してくれます。

このコードでAttributeErrorが発生します。要素が見つからない場合の処理を追加してください。

エラー: AttributeError: 'NoneType' object has no attribute 'get_text'
コード: title = soup.find("h2").get_text()

修正後のコード:

# 安全な取得方法
title_elem = soup.find("h2")
title = title_elem.get_text(strip=True) if title_elem else ""

エラー2:動的コンテンツの読み込み待ち

JavaScriptでレンダリングされるコンテンツの場合、通常のrequestsでは取得できません。

エージェントへの指示:

このサイトはJavaScriptで動的にコンテンツが生成されます。
SeleniumまたはPlaywrightを使ったコードに変更してください。

要件:
- 要素が表示されるまで最大10秒待機
- タイムアウト時はエラーログを出力

生成されたコード例:

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 scrape_dynamic_content(url: str):
    driver = webdriver.Chrome()
    try:
        driver.get(url)
        # 要素が表示されるまで待機
        element = WebDriverWait(driver, 10).until(
            EC.presence_of_element_located((By.CLASS_NAME, "job-item"))
        )
        # スクレイピング処理
        # ...
    finally:
        driver.quit()

実践例3:リファクタリング支援

既存のスクレイピングコードを、コーディングエージェントの支援でリファクタリングする例です。

リファクタリング前

# 重複が多いコード
def scrape_site_a():
    response = requests.get("https://site-a.com/jobs")
    soup = BeautifulSoup(response.text, "html.parser")
    jobs = []
    for item in soup.find_all("div", class_="job"):
        title = item.find("h2").text
        company = item.find("span", class_="company").text
        jobs.append({"title": title, "company": company})
    return jobs

def scrape_site_b():
    response = requests.get("https://site-b.com/listings")
    soup = BeautifulSoup(response.text, "html.parser")
    jobs = []
    for item in soup.find_all("div", class_="listing"):
        title = item.find("h3").text
        company = item.find("span", class_="firm").text
        jobs.append({"title": title, "company": company})
    return jobs

エージェントへの指示:

このコードをリファクタリングしてください。

要件:
- 共通処理を関数に抽出
- サイトごとの設定を辞書で管理
- 型ヒントを追加
- エラーハンドリングを追加

リファクタリング後

from typing import List, Dict, Optional
from dataclasses import dataclass

@dataclass
class ScrapingConfig:
    url: str
    item_selector: str
    title_selector: str
    company_selector: str

def safe_extract(element, selector: str, default: str = "") -> str:
    """安全に要素を取得"""
    found = element.select_one(selector)
    return found.get_text(strip=True) if found else default

def scrape_jobs(config: ScrapingConfig) -> List[Dict[str, str]]:
    """汎用的なスクレイピング関数"""
    try:
        response = requests.get(config.url, headers=get_headers(), timeout=10)
        response.raise_for_status()
        
        soup = BeautifulSoup(response.text, "html.parser")
        jobs = []
        
        for item in soup.select(config.item_selector):
            job = {
                "title": safe_extract(item, config.title_selector),
                "company": safe_extract(item, config.company_selector),
            }
            jobs.append(job)
        
        return jobs
    except requests.RequestException as e:
        logging.error(f"Scraping failed for {config.url}: {e}")
        return []

# サイトごとの設定
SITE_CONFIGS = {
    "site_a": ScrapingConfig(
        url="https://site-a.com/jobs",
        item_selector="div.job",
        title_selector="h2",
        company_selector="span.company"
    ),
    "site_b": ScrapingConfig(
        url="https://site-b.com/listings",
        item_selector="div.listing",
        title_selector="h3",
        company_selector="span.firm"
    ),
}

コーディングエージェント活用のベストプラクティス

1. 段階的な開発

一度にすべてを生成させるのではなく、小さな単位で段階的に開発します。

  1. 基本的なHTTPリクエストとHTML解析
  2. データ抽出ロジック
  3. エラーハンドリング
  4. リトライ機能
  5. データ正規化

2. コードレビューを必ず行う

エージェントが生成したコードは、必ず人間がレビューします。

  • セキュリティリスクの確認
  • パフォーマンスの確認
  • 可読性の確認
  • エッジケースの確認

3. プロンプトの改善

同じプロンプトを繰り返し使うのではなく、結果を見てプロンプトを改善します。

改善例:

# 最初のプロンプト
スクレイピングコードを書いて

# 改善後
Pythonでスクレイピングコードを作成してください。
- 対象サイト: https://example.com
- 取得データ: タイトル、価格、在庫数
- 要件: リトライ3回、待機1-3秒、CSV出力
- ライブラリ: requests, BeautifulSoup, pandas

4. 既存コードとの統合

エージェントが生成したコードを、既存のプロジェクトに統合する際は、コーディング規約やアーキテクチャに合わせて調整します。

注意点と制限事項

エージェントの限界

コーディングエージェントは強力ですが、完璧ではありません。

  • 最新のライブラリ情報: エージェントの学習データが古い場合がある
  • サイト固有の仕様: 各サイトの特殊な仕様は理解できない
  • セキュリティ: 生成されたコードにセキュリティホールがある可能性

必ず確認すべきこと

  1. robots.txtの確認: スクレイピングが許可されているか
  2. 利用規約の確認: サイトの利用規約を遵守しているか
  3. レート制限: 適切なリクエスト間隔を設定しているか
  4. エラーハンドリング: 想定外のエラーに対応できているか

まとめ

CursorやClaude Codeなどのコーディングエージェントを活用することで、Pythonスクレイピングコードの開発を大幅に効率化できます。

効果的な活用方法:

  • 具体的で構造化されたプロンプトを使用
  • 生成されたコードを必ずレビュー・改善
  • 段階的に開発を進める
  • エラーハンドリングとセキュリティを意識

改善前:

  • スクレイピングコードの作成に数時間かかる
  • エラー修正に時間がかかる
  • コードの重複が多い

改善後:

  • エージェントの支援で開発時間を短縮
  • エラー修正が迅速
  • リファクタリングで保守性が向上

コーディングエージェントは「コードを書くツール」ではなく、「開発を加速するパートナー」として活用することで、より効率的な開発が可能になります。


関連リンク: