React.jsはフロントエンドのライブラリであるため、スクレイピングを行う際にはCORS(クロスオリジン制約)や適切なデータ取得方法について理解することが重要です。
React.jsでスクレイピングをする際の問題点
React.jsはフロントエンドの技術なので、通常のバックエンドで行うスクレイピングとは異なり、いくつかの制約があります。
CORSの制約
ブラウザ上でスクレイピングを行う場合、異なるオリジン(ドメイン)からデータを取得しようとするとCORS制約によりブロックされることがあります。
Javascriptによるレンダリング
多くのWebサイトは、Javascriptを使ってデータを非同期にロードしているため、単純なfetchではHTMLにデータが含まれていないケースが多いです。
例えば、以下のページが React.js や Vue.js で動的にデータを読み込む場合、普通のHTTPリクエストではデータを取得できません。
<div id="app">
<p>Loading...</p>
</div>
React.jsがデータを読み込んだあと、DOMが変更されてappの中にデータが入ります。しかし、通常のfetchではjavascriptが実行される前の状態しか取得できません。
解決策①
CORSの制約を回避するために、バックエンド(サーバー)を用意し、フロントエンド経由でリクエストを送る方法です。
①フロントエンド(React.js)は、自分のサーバー(Node.js/Expressなど)にリクエストを送る
②サーバー側がfetch()やaxiosを使い、外部のwebサイトからデータを取得する
③React.jsはサーバーからのレスポンスを受け取る
⭐️Node.js+Expressのサーバーを作る
const express=require('express');
const axios = require("axios");
const cors = require("cors");
const app = express();
const PORT = 3001;
// CORSを許可
app.use(cors());
app.get("/proxy", async (req, res) => {
try {
const response = await axios.get("https://example.com/data");
res.json(response.data);
} catch (error) {
res.status(500).json({ error: "データ取得に失敗しました" });
}
});
app.listen(PORT, () => console.log(`サーバー起動: http://localhost:${PORT}`));
⭐️React.js側でデータを取得
import { useEffect, useState } from "react";
const Scraper = () => {
const [data, setData] = useState(null);
useEffect(() => {
fetch("http://localhost:3001/proxy")
.then(response => response.json())
.then(result => setData(result))
.catch(error => console.error("Error:", error));
}, []);
return (
<div>
<h1>スクレイピング結果</h1>
{data ? <pre>{JSON.stringify(data, null, 2)}</pre> : <p>読み込み中...</p>}
</div>
);
};
export default Scraper;
メリット
・CORSの制約を回避することができる(フロントエンドは自分のサーバーを経由するので、外部のサイトには直接アクセスしない)
・Webサイト側がAPIを提供していない場合でもデータを取得することができる
デメリット
・サーバーをセットアップする必要がある
・サーバーの負荷が増える
解決策②:ヘッドレスブラウザ(Puppeteer)を利用する
普通のfetch()では、Javascriptで動的にレンダリングされるページのデータを取得することはできない。そのため、Puppeteerというツールを使用してブラウザを自動操作しながらデータを取得する必要がある。
Puppeteerとは?
Puppeteerは、Google Chromeをプログラムで自動操作するためのツールです。
・Javascriptで描画されたページでもデータを取得することができる
・ログインが必要なサイトでも操作できる
Puppeteerでスクレイピングを行う
const puppeteer = require("puppeteer");
const scrapeData = async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto("https://example.com");
const data = await page.evaluate(() => {
return document.querySelector("h1").innerText;
});
await browser.close();
return data;
};
scrapeData().then(console.log);
メリット
・Javascriptでレンダリングされるページでもデータを取得できる
・フォームの送信やページのスクロールなどブラウザの操作が可能
デメリット
・axiosやfetch()に比べて動作が重い(ブラウザを起動するため)
・サーバー環境によってはセットアップが必要