Open2
Cloudflare Browser Rendering (Puppeteer)
基本的にこの通りでできます。CFに要課金です。
setup
まずCloudflareに月額$5ドル払います。これをしないとローカルで試しても利用できません(どちらにせよ--remote付けないとだけど)。
雛形作成。
npm create cloudflare@latest
インストール
npm install @cloudflare/puppeteer --save-dev
KVの追加
npx wrangler kv:namespace create BROWSER_KV_DEMO
npx wrangler kv:namespace create BROWSER_KV_DEMO --preview
#:schema node_modules/wrangler/config-schema.json
name = "jmobile-puppeteer"
main = "src/index.ts"
compatibility_date = "2024-04-23"
compatibility_flags = ["nodejs_compat"]
browser = { binding = "MY_BROWSER" }
kv_namespaces = [
{ binding = "BROWSER_KV_DEMO", id = "",preview_id = "" }
]
ソースコード
src/index.ts
import puppeteer from "@cloudflare/puppeteer";
interface Env {
MY_BROWSER: Fetcher;
BROWSER_KV_DEMO: KVNamespace;
}
export default {
async fetch(request, env): Promise<Response> {
const { searchParams } = new URL(request.url);
let url = searchParams.get("url");
let img: Buffer;
if (url) {
url = new URL(url).toString(); // normalize
img = await env.BROWSER_KV_DEMO.get(url, { type: "arrayBuffer" });
if (img === null) {
const browser = await puppeteer.launch(env.MY_BROWSER);
const page = await browser.newPage();
await page.goto(url);
img = (await page.screenshot()) as Buffer;
await env.BROWSER_KV_DEMO.put(url, img, {
expirationTtl: 60 * 60 * 24,
});
await browser.close();
}
return new Response(img, {
headers: {
"content-type": "image/jpeg",
},
});
// biome-ignore lint/style/noUselessElse: <explanation>
} else {
return new Response("Please add an ?url=https://example.com/ parameter");
}
},
} satisfies ExportedHandler<Env>;
実行
npx wrangler dev --remote
<LOCAL_HOST_URL>/?url=https://zenn.dev/
にアクセスするとスクショが表示されます。
いやめっちゃ長!?
普通にKV邪魔なので外してスクショだけ返すようにしてますが、それでも全然余裕で楽にスクレイピングできます。簡単なサイトであれば手元でPuppeteerを起動せずにこのスクショの撮影だけでいけるということがわかりました。
import puppeteer from "@cloudflare/puppeteer";
interface Env {
MY_BROWSER: Fetcher;
}
export default {
async fetch(request, env): Promise<Response> {
const { searchParams } = new URL(request.url);
const url = "https://....";
const browser = await puppeteer.launch(env.MY_BROWSER);
const page = await browser.newPage();
await page.goto(url);
// ユーザーIDとパスワードを入力してログイン
await page.type("#user_id", "");
await page.type("#password", "");
await page.click("#login");
await page.waitForNavigation();
await page.goto("https://....");
const img = (await page.screenshot()) as Buffer;
await browser.close();
return new Response(img, {
headers: {
"content-type": "image/jpeg",
},
});
},
} satisfies ExportedHandler<Env>;