Web scraping avec Claude Code
Découvrez web scraping avec Claude Code. Conseils pratiques et exemples de code inclus.
WebスクレイピングをClaude Codeで効率化する
Webスクレイピングは、データ収集や監視、競合分析などに活用される技術です。Claude Codeを使えば、HTML解析からデータ整形まで一貫したスクレイピングスクリプトを短時間で構築できます。
Cheerioで静的ページをスクレイピング
JavaScriptレンダリングが不要なページにはCheerioが最適です。
> Cheerioでニュースサイトの記事タイトルとリンクを取得するスクリプトを作って。
> リトライ機能とレート制限も入れて。
import * as cheerio from "cheerio";
interface Article {
title: string;
url: string;
date?: string;
}
async function fetchWithRetry(
url: string,
retries = 3,
delay = 1000
): Promise<string> {
for (let i = 0; i < retries; i++) {
try {
const res = await fetch(url, {
headers: {
"User-Agent": "Mozilla/5.0 (compatible; MyBot/1.0)",
},
});
if (!res.ok) throw new Error(`HTTP ${res.status}`);
return await res.text();
} catch (error) {
if (i === retries - 1) throw error;
console.log(`リトライ ${i + 1}/${retries}...`);
await new Promise((r) => setTimeout(r, delay * (i + 1)));
}
}
throw new Error("Unreachable");
}
async function scrapeArticles(url: string): Promise<Article[]> {
const html = await fetchWithRetry(url);
const $ = cheerio.load(html);
const articles: Article[] = [];
$("article, .article, .post").each((_, element) => {
const titleEl = $(element).find("h2 a, h3 a, .title a").first();
const title = titleEl.text().trim();
const href = titleEl.attr("href");
const date = $(element).find("time, .date").first().text().trim();
if (title && href) {
articles.push({
title,
url: new URL(href, url).toString(),
date: date || undefined,
});
}
});
return articles;
}
Puppeteerで動的ページをスクレイピング
SPAやJavaScriptで描画されるページにはPuppeteerを使います。
import puppeteer from "puppeteer";
interface ProductData {
name: string;
price: number;
rating: number;
imageUrl: string;
}
async function scrapeDynamicPage(url: string): Promise<ProductData[]> {
const browser = await puppeteer.launch({ headless: true });
const page = await browser.newPage();
// 不要なリソースをブロックして高速化
await page.setRequestInterception(true);
page.on("request", (req) => {
const type = req.resourceType();
if (["image", "stylesheet", "font"].includes(type)) {
req.abort();
} else {
req.continue();
}
});
await page.goto(url, { waitUntil: "networkidle2" });
// 無限スクロールで全データを読み込む
let previousHeight = 0;
while (true) {
const currentHeight = await page.evaluate(() => document.body.scrollHeight);
if (currentHeight === previousHeight) break;
previousHeight = currentHeight;
await page.evaluate(() => window.scrollTo(0, document.body.scrollHeight));
await new Promise((r) => setTimeout(r, 1500));
}
const products = await page.evaluate(() => {
const items = document.querySelectorAll(".product-card");
return Array.from(items).map((item) => ({
name: item.querySelector(".product-name")?.textContent?.trim() || "",
price: parseFloat(
item.querySelector(".price")?.textContent?.replace(/[^0-9.]/g, "") || "0"
),
rating: parseFloat(
item.querySelector(".rating")?.getAttribute("data-value") || "0"
),
imageUrl: item.querySelector("img")?.getAttribute("src") || "",
}));
});
await browser.close();
return products;
}
データの保存と構造化
取得したデータをJSON、CSV形式で保存します。
import fs from "fs/promises";
async function saveAsJson(data: unknown[], filePath: string) {
await fs.writeFile(filePath, JSON.stringify(data, null, 2), "utf-8");
console.log(`${filePath} に ${(data as any[]).length}件を保存しました`);
}
function toCsvString(data: Record<string, unknown>[]): string {
if (data.length === 0) return "";
const headers = Object.keys(data[0]);
const rows = data.map((row) =>
headers.map((h) => {
const val = String(row[h] ?? "");
return val.includes(",") || val.includes('"')
? `"${val.replace(/"/g, '""')}"`
: val;
}).join(",")
);
return [headers.join(","), ...rows].join("\n");
}
async function saveAsCsv(data: Record<string, unknown>[], filePath: string) {
const csv = toCsvString(data);
await fs.writeFile(filePath, csv, "utf-8");
console.log(`${filePath} に保存しました`);
}
定期実行とスケジューリング
import cron from "node-cron";
function startScheduledScraping() {
// 毎日9時に実行
cron.schedule("0 9 * * *", async () => {
console.log(`[${new Date().toISOString()}] スクレイピング開始`);
try {
const articles = await scrapeArticles("https://example.com/news");
const timestamp = new Date().toISOString().split("T")[0];
await saveAsJson(articles, `./data/articles-${timestamp}.json`);
} catch (error) {
console.error("スクレイピングエラー:", error);
}
});
console.log("スケジュール設定完了(毎日9:00実行)");
}
倫理的な配慮
Webスクレイピングを行う際は、以下の点に注意してください。
- robots.txtを確認し、クローリングが許可されているか確認する
- リクエスト間隔を適切に設けてサーバーに負荷をかけない
- 利用規約を確認し、スクレイピングが禁止されていないか確認する
- 取得したデータの著作権と利用目的を考慮する
Markdown形式でデータを加工する方法はMarkdown処理・変換を参照してください。CLIツールとして構築する場合はCLIツール開発もご覧ください。
Summary
Claude Codeを使えば、静的・動的ページのスクレイピング、データ整形、定期実行まで含めたスクレイピングシステムを短時間で構築できます。セレクタの指定やデータ変換も自然言語で指示するだけです。
詳しくはClaude Code公式ドキュメントを参照してください。
Related Posts
Comment booster vos projets personnels avec Claude Code [Avec exemples]
Apprenez à accélérer considérablement vos projets de développement personnels avec Claude Code. Inclut des exemples concrets et un workflow pratique de l'idée au déploiement.
Comment automatiser le refactoring avec Claude Code
Apprenez à automatiser efficacement le refactoring de code avec Claude Code. Inclut des prompts pratiques et des patterns de refactoring concrets pour des projets réels.
Guide complet de configuration CORS avec Claude Code
Découvrez le guide complet de configuration CORS avec Claude Code. Conseils pratiques et exemples de code inclus.