FirebaseのFunctionsでスクレイピングするときの注意事項

6 min read 4

先日、毎月書いた記事一覧を取得するSlackアプリでZennの記事が取得できなくなるという事象が発生しました。
原因はZennの記事一覧取得API(非公式)に403でアクセスできなくなっていたためでしたが、
もともと非公式のAPIを使わせていただいていたものだったので、これは仕方ないと、スクレイピングで記事を取得するように修正をすることに。

その際、FirebaseのFunctions上でPlaywrightを動かすのにちょっと工夫が必要だったのでそれをここに残しておきます。

2021/06/08追記

Zennの開発者、catnoseさんよりコメントをいただきまして

ちなみにAPIをアクセス禁止にしたわけではなく、
https://api.zenn.dev/*がhttps://zenn.dev/api/*に変わった感じです!

とのことでした。

上記も公式で提供しているものではないため、今後も変更される可能性があります!!!

また、Kawamata Ryoさんより、メモリの変更はコードで設定することもできるとの情報をいただきました!以下のようにFunctionsのオプションとしてmemoryを指定することでもメモリ変更が可能なようです。

const runtimeOpts = {
  timeoutSeconds: 300,
  memory: '1GB'
}

exports.myStorageFunction = functions
  .runWith(runtimeOpts)
  .storage
  .object()
  .onFinalize((object) = > {
    // do some complicated things that take a lot of memory and time
  });

なお、詳細は公式を確認していただきたいのですが、指定できるmemoryの値は以下を指定できるみたいです。

  • 128MB
  • 256MB
  • 512MB
  • 1GB
  • 2GB
  • 4GB
  • 8GB

環境

  • macOS Big Sur 11.3.1
  • Flutter 2.2.0

ポイント

  • playwright-aws-lambdaを使う
  • デフォルトのメモリ容量256MBだと足りないのでメモリを増やす必要がある

playwright-aws-lambdaを使う

最初、通常のPlaywrightをインストールして使っていたのですが、以下のようにchromiumを起動できず。

2021-06-01T13:43:21.934Z ? firestore-onCreate: browserType.launch: Failed to launch chromium because executable doesn't exist at /root/.cache/ms-playwright/chromium-878941/chrome-linux/chrome
2021-06-01T13:43:21.934Z ? firestore-onCreate: Try re-installing playwright with "npm install playwright"
2021-06-01T13:43:21.934Z ? firestore-onCreate: Error
2021-06-01T13:43:21.934Z ? firestore-onCreate:     at Object.captureStackTrace (/workspace/node_modules/playwright/lib/utils/stackTrace.js:50:19)
2021-06-01T13:43:21.934Z ? firestore-onCreate:     at Connection.sendMessageToServer (/workspace/node_modules/playwright/lib/client/connection.js:65:48)
2021-06-01T13:43:21.934Z ? firestore-onCreate:     at Proxy.<anonymous> (/workspace/node_modules/playwright/lib/client/channelOwner.js:64:61)
2021-06-01T13:43:21.934Z ? firestore-onCreate:     at /workspace/node_modules/playwright/lib/client/browserType.js:60:67
2021-06-01T13:43:21.934Z ? firestore-onCreate:     at BrowserType._wrapApiCall (/workspace/node_modules/playwright/lib/client/channelOwner.js:77:34)
2021-06-01T13:43:21.934Z ? firestore-onCreate:     at BrowserType.launch (/workspace/node_modules/playwright/lib/client/browserType.js:51:21)
2021-06-01T13:43:21.934Z ? firestore-onCreate:     at Object.exports.getZennArticleUrlsOfMonth (/workspace/lib/blog/zenn-client.js:14:49)
2021-06-01T13:43:21.934Z ? firestore-onCreate:     at /workspace/lib/firestore/blog-url-sender.js:25:46
2021-06-01T13:43:21.934Z ? firestore-onCreate:     at processTicksAndRejections (internal/process/task_queues.js:97:5)

調べてみると同じような現象に遭遇している方はいて、

  • 特定バージョンのchromiumをダウンロード
  • 上記を使うようにパスを設定
    すればOKらしいみたいだが、Functions上でどう設定するかよくわからなかったのでパス。

https://gkushang.medium.com/playwright-failed-to-launch-browsers-how-to-solve-8b01d03fe5b9

そこで、chromiumとPlaywrightがパッケージされたplaywright-aws-lambdaというパッケージを発見したのでこちらを利用すると上記のエラーは解消されました。なお、こちらのパッケージはREADMEをみるとわかりますが、Cloud Functionsでも使えます。

https://github.com/JupiterOne/playwright-aws-lambda

どうもplaywright-aws-lambdaを使わずに、Playwrightを使えている人もいるみたいなのですが、そのあたり何が違うのかはまだわかっていません。

デフォルトのメモリ容量256MBだと足りないのでメモリを増やす必要がある

playwright-aws-lambdaを導入することでchromiumを起動できないというエラーは解消することができました。
ところが、今度は以下のエラーに遭遇しました。

  "textPayload": "Error: memory limit exceeded. Function invocation was interrupted."
  // 省略

メモリ制限に引っかかってしまいました。こちら解消するにはFunctionsのメモリを増やす必要があります。
※デフォルトだと256MBでした。

メモリを増やすにはFirebaseの管理画面上からではなく、GCPのコンソール上から設定します。

  1. GCPのコンソールにアクセス

Image from Gyazo

  1. メモリを上げたいFunctionsがあるプロジェクト選択して以下の画面を開く

Image from Gyazo

  1. 左のハンバーガメニューからを開いてCloud Functionsを選択

Image from Gyazo

  1. メモリを増やしたい関数を選択してクリック

Image from Gyazo

  1. 関数の詳細画面で「編集」をクリックする

Image from Gyazo

  1. 「割り当てられるメモリ」を増やして「次へ」を選択

Image from Gyazo

  1. 「デプロイ」を押して完了。あとは反映されるまで待つ!

Image from Gyazo

恥ずかしながらメモリを増やせることを知らず、よく出入りしている「エンジニアと人生コミュニティ」で@mogaさんにヒントをもらいました!あざます!!

参考