やりたいこと
Cloudflare WorkersとD1を使って、定期的にサイトをスクレイピングするWorkerを作ってみます。
Workers環境を作成する。
Workerをセットアップします
下記のnpm createを叩き、Workersを作成します。
$ $ npm create cloudflare@latest
D1をセットアップする
下記のコマンドで、d1データベースを作成します。
$ npx wrangler d1 create <DATABASE_NAME>
wrangler.toml
で、d1をバインディングします。
[[d1_databases]]
binding = "DB" # available in your Worker on env.DB
database_name = "<DATABASE_NAME>"
database_id = "<unique-ID-for-your-database>"
D1へテーブルを作成する
サンプルなのでSQLは適当です。
各々必要なカラムを持ったテーブルを作ってください。
CREATE TABLE IF NOT EXISTS Test (Title TEXT);
schemaファイルをローカルの環境で叩きます。
npx wrangler d1 execute <DB_NAME> --local --file='./schema.sql'
WorkersとD1のチュートリアルを一度走っておくと分かりやすいです。
Cronトリガーを設定します。
wrangler.toml
を編集します。
triggers
を追加し、UTC時間を配列の中に入れておきます。
[triggers]
# Schedule cron triggers:
# - At every 3rd minute
# - At 3PM on first day of the month
# - At 11:59PM on the last weekday of the month
crons = [ "*/3 * * * *", "0 15 1 * *", "59 23 LW * *" ]
下記の形式で入力ができます。
ChatGPTにお願いするか、ブラウザのGUIから入力するのが正確で楽でした。
フィールド | 値 | 文字 |
---|---|---|
分 | 0-59 | * , - / |
時 | 0-23 | * , - / |
月の日 | 1-31 | * , - / L W |
月 | 1-12、大文字小文字を区別しない3文字の略語(例: “JAN”, “aug”など) | * , - / |
曜日 | 1-7、大文字小文字を区別しない3文字の略語(例: “MON”, “fri”など) | * , - / L # |
src/index.ts
を編集して、スクレイピング処理を追加します。
ブラウザから編集する方法
Cloudflareダッシュボードの、「Workers/概要」から、作ったプロダクトへアクセスします。
タブメニューの「トリガー」へ移動し、下の方にCronトリガーの項目があるので、ここで追加と削除が行なえます。
Cronの削除方法
Cronsトリガーをwrangler.tomlから削除する際は、丸ごと消してはCronトリガーが削除されません。
crons=[]
と空の配列を渡す必要があります。
スクレイピングする処理を追加する
スクレピングライブラリを追加する
軽量で高速なスクレイピングライブラリのcherrio
をインストールします。
$ npm install cheerio
src/index.js
へ処理を追加する
expord default
内へ、async scheduled
を追加します。
これで、この関数内の処理がcronトリガーで叩かれるようになります。
export default {
async scheduled(event, env, ctx) {
// ここに処理を追加していく。
},
};
スクレイピングの処理を追加する
cheerioでスクレピングする処理を追加します。
export default {
async scheduled(event, env, ctx) {
const url = 'https://example.com/';
const response = await fetch(url);
const data = await response.text();
const $ = cheerio.load(data);
const h1Text = $('h1').text();
console.log(h1Text);
};
処理をテストする
wrangler dev
時に--test-scheduled
を渡してあげてから、curlで叩くとテストができます。
h1のテキスト Example Domain
がターミナルに表示されると思います。
$ wrangler dev --test-scheduled
$ curl "http://localhost:8787/__scheduled?cron=*+*+*+*+*"
D1へ追加する
D1へINSERTする
チュートリアルでやったように、INSERT文でスクレピングしたテキストをD1へ追加します。
export default {
async scheduled(event, env, ctx) {
const url = 'https://example.com/';
const response = await fetch(url);
const data = await response.text();
const $ = cheerio.load(data);
const h1Text = $('h1').text();
console.log(h1Text);
await env.DB.prepare(`
insert into Test (title) values (?)
`).bind(h1Text).run()
};
確認する
ローカルのD1データベースは、.wrangler/state/v3/d1/miniflare-D1DatabaseObject
内のsqliteファイルに入っているので、こちらを確認することで確認できます。
自分は、VSCodeのSQLiteViewerを使って確認しています。
デプロイする
動作を確認したらデプロイします。
$ npx wrangler d1 execute <DB_NAME> --local --file='./schema.sql'
$ npx wrangler deploy
Cloudflare dashboardに移動し、無事デプロイされているか、cronで設定された時間になったら、無事Workerが動いてD1にデータが追加されているかを確認して終了です。
この記事では、スクレピング部分を適当に済ませていますが、ここを目的のサイトに対応させることで、勝手にデータを拾って保存できる環境を高速かつ低コストで実装できるので、個人開発で情報を取り扱う場合にはとても便利に感じました。
参考