LoginSignup
5
2

CloudflareWorkers+D1+cheerioでスクレイピングを定期実行してみる

Posted at

やりたいこと

Cloudflare WorkersとD1を使って、定期的にサイトをスクレイピングするWorkerを作ってみます。

Workers環境を作成する。

Workerをセットアップします

下記のnpm createを叩き、Workersを作成します。

$ $ npm create cloudflare@latest

D1をセットアップする

下記のコマンドで、d1データベースを作成します。

$ npx wrangler d1 create <DATABASE_NAME>

wrangler.tomlで、d1をバインディングします。

wrangler.toml
[[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時間を配列の中に入れておきます。

wrangler.toml
[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/概要」から、作ったプロダクトへアクセスします。
image.png

タブメニューの「トリガー」へ移動し、下の方にCronトリガーの項目があるので、ここで追加と削除が行なえます。

image.png

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にデータが追加されているかを確認して終了です。

この記事では、スクレピング部分を適当に済ませていますが、ここを目的のサイトに対応させることで、勝手にデータを拾って保存できる環境を高速かつ低コストで実装できるので、個人開発で情報を取り扱う場合にはとても便利に感じました。

参考

5
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
2