Javascript 難しいですよね。
私はもっぱらバックエンドの弱小PHPerなので、フロントの技術はさっぱりなんです。
なので、これまではJavascriptは本当にたしなむ程度しか触っていませんでした。
ところがここ数週間の間、どうしてもJavascriptと(というかNode.js)少し真剣に向き合う機会があり、かなり悪戦苦闘する日々が続きました。
私のようにC言語やPHP出身のプログラマだとJavascript(というかNode.js)の基本概念って、慣れるのにすごくハードルが高いんじゃないかな、と思います(あくまで個人的な感想ですが)。
つくづく世のJavascript屋さんは本当に優秀なんだなーと感服するばかりなのです。
何回にも分けて記事を書くことで、自分がつまづいた場所をなるべく詳細に記録していきたいと思います(で、できるかな!?)。なので、このシリーズを読み終わるころには以下のような技術を学んでもらえたらいいなと思います。
・Firebase function + Node.jsで実装する
・外部APIを叩く(HTTPリクエストを投げる)
・Firestore(データベース)にデータを登録する
・Cheerioでスクレイピングする
・Firebaseにアプリを公開する
・GAS(Google App Script)からアプリを呼び出す
・Node.jsの非同期処理(Promiseを使った実装)
すっごい偉そうに言ってますが、私ただの弱小PHPer、Javascriptに関しては学生以下レベルですので、あまり期待しないほうが良いかもです。
とあるWebサイトをスクレイピングしたい
この一連のシリーズでは、とあるサイトをスクレイピングしたいと思います。
しかも、今回は対象のサイトを一定間隔で、例えば30分おきにスクレイピングしたいのです。
ざっと考えて、PHPでやるならサーバーにスクレイピング用のスクリプトを置いて、cronで定期実行するかなぁと思うのですが、今回はやめました。
自分で新規にサーバ立てるのは少し面倒だし、お金かかるし・・・
このブログをホスティングしているエックスサーバーで、適当なところにスクリプトを置けば、お金はかからないし、手間もほとんどありませんが、なんとなくPHP + MySQLという構成以外の何かに手を出したかったのです。
今にして思えばこのナイーブな好奇心のせいで、ずいぶん苦労してしまったわけなんですが。
Firebase Functions + Node.js + Cloud Firestore + Cheerio + GAS という組合せで行くことに決定
そんなわけで、今回採用したのがFirebase Functions + Node.js + Cloud Firestore + Cheerio + GAS という組合せです。
この組合せにたどり着くまでにも、ずいぶん時間を浪費しましたが、その経緯はまた別の記事に譲ろうと思います。
私のようにPHP程度で生きている人間にとっては、どうも聞きなれない用語ばかりです。
ここで、簡単にそれぞれの用語について説明してみます。
Firebase Functions + Node.jsとは
Firebase Functionsの説明の前に、まずGoogleが展開しているFirebaseというサービスがあります。
このFirebaseというのは、mBaaSというけったいなサービスの名前なんですがmobile Backend as a Serviceの頭文字から来ているみたいです(詳しくは分かりません)。
mBaaSというのは、頑張って日本語で言ってみると「モバイルおよび Web アプリケーションのバックエンドサービス」らしいですよ。
まぁ、mBaaSが何なのかはそれほど重要ではありません。
Firebaseは従量課金制のサービスですが、個人利用程度の目的であれば、基本的に無料で使うことができます。
Firebaseでは、いろんなサービスを提供している(※1)のですが、そのうちのひとつがFirebase Functionsという位置づけになります。
たぶん、よく言われるGoogle Cloud Functionsとほとんど同義なんじゃないかと思います。
※1 いろんなサービスとは、静的なHTMLファイルのホスティングだったり、Firestoreというデータベースだったり、単なるストレージだったりします。
Firebase (の中の Firebase Functions) を使う最大の利点は、プログラムをホスティングするサーバーを用意しなくて良いところなんじゃないかと思います。
これまでは、PHPでもJAVAでもRubyでも、どのような言語を選んでも、とにかくどこかでホスティング環境を購入して、そこに自分が作ったプログラムをFTPソフトでアップロードする必要がありました。
例えばAWSでEC2を購入したり、どこかのWebホスティングサービスに契約したりする必要があります。
しかしFirebaseではもう最初っからGoogleがホスティング環境を用意してくれています。
Googleアカウントさえあれば、ほとんど無料で使うことができます。
私たちプログラマがすることは、プログラムを書いてアップロード(デプロイ)するだけ。
あとは勝手にプログラムがインターネットに公開されることになります。
このシリーズでは、Firebase Functions でAPIっぽいものをWebに公開し、そのAPIをGAS(Google App Script)から定期的に呼び出す、という構成で定期実行のスクレイピングをやってみたいと考えています。
少し前置きが長くなってしまいましたが、このFirebase Functionsを使うにあたって、基本的にはNode.jsで実装するのが一般的ということで、勉強がてらjavascript + Node.jsに手を出す運びとなったのでした。
次にNode.jsですが、私にとってNode.jsに対するイメージと言えば「javascriptがサーバーサイドで動くよ」程度の認識でした。
「いやいやいや、サーバサイドならPHPあればいいでしょ。わざわざJavascriptだなんて冗談が過ぎるヨ。新しい言語でやるにしても、これからやるなら断然Go言語だよねー」くらいに思っていたので、Node.jsは完全に軽視していました(ごめんよNode.js)。
しかし今回、Firebase (とFirebase Functions)のせいで、不本意にもNode.jsに足を突っ込まざるを得なくなってしまったというわけなんです(今でもNode.jsの必要性はイマイチ分かっていません汗)。
Cheerio とはNode.js用のスクレイピングモジュール
Node.jsでは、いろんなライブラリ的な関数群が提供されています。Node.jsではこのようなライブラリをモジュールと呼ぶみたいです。
そして、私が調べた限り、Node.jsでスクレイピングをするならこのCheerioというモジュールが最も一般的らしいので、これを採用することにしました。
一般的に、スクレイピングをするなら優秀なHTMLのパーサーが必要になると思います。
要は、HTMLのテキストを読み込んで、その中のタグ構造をプログラムが扱いやすいように変換する機能です(これをパース=解析と呼びます)。
このCheerioというモジュールを使うと、jQueryのセレクタと同じような記法で要素を取得することができます。
ちなみに、PHPを使ってスクレイピングするなら、phpQueryというライブラリが存在しています。こちらもまたjQuery様式で要素を取得することができるようになるライブラリです。
やっぱりjQueryライクに要素を取得できるっていうのは、多くのプログラマにとって需要があるんですね。
GAS (Google App Script)
最後に、GAS (Google App Script) になります。
Google App Script は、Googleが提供する色んなサービスをプログラムから利用できるようにするものって感じだと思います。
もう少し具体的な例を挙げると、例えばGoogle Spread Sheet にエクセルのVBA的なスクリプトを実装できたり、Spread Sheetの内容を使ってGmailにメールの下書きを作成したり、なんてことができると思います(やったことがないので断言できないのですが、、、)。
GASが対応しているGoogleのサービスは非常に多岐にわたっています。
おなじみのGmail, Google Calendar, Google Spread Sheet, Google Drive などなど、数え上げたらきりがありませんが、これらのサービスをGASで連携させると、いろんな場面でオフィスワークの自動化ができると思います。
で、今回はGASをどこで使うかと言うと、Firebase Functions でWebに公開したAPIを、定期的に実行する用途で使います。
実は、これはGASでやる必要はありません。
GASを選んだ理由は、Webリクエストを定期的に実行できるからです。
こちらもサーバーを持たなくて良いので、Firebase Functionsで公開したアプリ(API)を叩くのにちょうど良いかな、と思ったからです。
Firebase Functionsでも、APIを定期的に実行する機能はあるようですが、少しややこしそうだったのと、ほんの少しお金がかかりそうだったので止めました(月間数十円レベルだと思いますが)。
ちょっと前書きというか能書きが長くなったので続きは次回にします。
コメント