自サイトでスクレイピングしたデータを加工して、表示しているものがあります。
その過去の流れを振り返ってみました。
perl 期
最初は、perlのWWW::Mechanizeを利用していました。データを置換後、txtファイルに保存していました。
良かった点
- リンクを辿るとか、初学者でも簡単に理解できた。
- そのままperlで置換するので気楽だった
悪かった点
- いろいろと機能を追加していくと、散らかった感じになった。
- プログラムを分けて作るのがしんどくなった(perlゆえ?)
感想
perlスクリプトをcronで定期実行しました。
はじめてのスクレピング体験ということで、データを取得、表示できたところに喜びを感じた。
また、気軽にスクレイピングするのに、winでもlinuxでも同じような感じで動かせたところがよかった。
だんだん複雑な機能を追加していくにつれ、機能をファイルごとに分割したい欲求がたかまりました。
期間を空けてソースを見たときに、我ながら「何だこれ?」感のある散らかったコードでした。
置換部分は楽だったのを覚えています。
しかし、今からまた使うか?と聞かれたら答えはNOです、「旧車のよさ」みたいな感覚です。
Go TXT保存期
Goのソースをサーバー上でコンパイルして、cronで定期実行しました。
良かった点
- Goを触るきっかけになった
- 思ったより簡単に実装出来て、Goに親しみを感じた。
悪かった点
- パッケージ管理のpath概念がややこしかった(nodeのようなイメージかと思っていた)
- クロスコンパイルしなかったので、winのPC -> Gitレポジトリ -> サーバー上でコンパイル の手間が面倒。
github.com/PuerkitoBio/goquery でスクレイピングし始めました、データはperl期と同じフォーマットのtxtファイルでした。
Goを知って魅力的に感じたのと(Google製)と、コンパイルするので速いという情報から、perlからGoに移行しました。
表示部分のPHPを変えたくなかったので、perl期と同じtxtフォーマットで保存するよう作りました。
当初、GOROOT,GOHOME,SRCディレクトリなど、Go独特の決まりごと概念理解できず、パッケージのインポートなどでまごつきました。
のちにgo.modが使えるようになったとき便利で安心しました。
スクレイピング本体は goquery を利用しました、DOMをクエリで見つけて、Eachで回す処理はJSなど、あらかじめ体験していた概念と似ており基本部分をすばやく理解できました。
保存したtxtファイルをクリーニング(不要な情報の除去)などは、perlを書いてcronで動かして置換しました。
Go MYSQL保存期
TXTファイルに保存していたのを、MYSQLに保存しました。
理由は、MYSQLに入れておけばLINEアプリと連携したりなど、なにかと将来的に扱いやすいだろうと考えたからです。
また、サイト自体のアクセス数が増加し、TXTファイルへの読み取りアクセスがかなりの数になっていたはずなので問題が生じる前に手を打とうというのもありました。
上記のGoプログラムにMYSQLに保存する部分を追加しました、特に問題ありませんでした。
Goの流れ
- データの構造体作る
- 1の構造体の入るスライスを作る
- スレイピングデータを置換後、構造体へ代入
- 構造体をスライスへ追加
- スクレイピング完了後、スライスをループ
- 構造体をMYSQLへinsert
こんな感じで作りました。
この更新の際に、Joomlaの独自componetを作成しました。
スクレイピングしたMYSQLのデータを表示するcomponentを自作しました。
Joomla!component開発はクセが強く(viewがmodelのメソッドにgetつけて呼ぶところなど)コード量の割に苦戦しました。
しかし、jommla!APIのクセが理解出来たら、希望通りの機能を実装出来ました。
Node puppeteer MYSQL期
puppetteerをヘッドレスでcronから定期実行しました。
ついにスクレイピング元がJSでのDOM生成100%となり、goqueryではスクレイピング出来なくなりました。
Node puppeteer のヘッドレスブラウザの出番だろうということで、作り直しました。
良かった点
- 希望するDOMを割と短いコードでスクレイピングできた
悪かった点
- Nodeを書いたことがなかったので、初学に時間がかかった
- puppetteerがawaitだらけになるところなど、処理の流れの理解に時間がかかった
- GCPのGCEでインスタンスを動かしていますが、メモリを1Gから2Gに増量せねばならなくなった
- CPU消費量が増えた
Node自体全然さわってなかったので、見よう見まねでpuppetteerスクレイピングとMYSQLへのinsertを作りました。
まったくの初学者だったので、時間がかかってしまった。
puppetteerの page.evaluateを使いこなすっていうところまでの理解に時間がかかりました。
出来た後は、素直に動き続けていましたが、CPUやメモリなどサーバーリソースを食うのが気になりました。
Node puppeteer GCP functions MYSQL期
puppetteerをGCP functionsのHTTP関数に移行、GCEインスタンス内のMYSQLにインサート、呼び出しはGCEのcronからcurlで。
サーバーリソースを食うのが何かしら気になって、GCP functionsへスクレイピングを移行しました。
コードの変更が極小で済んだので助かりました。
良かった点
- GCEのメモリを1GBの減らすことが出来た
- GCEインスタンスのリソース消費量が減った
悪かった点
- functionsのデプロイをfirebaseと同じかと思っていたら、functionsのコンソール、すなわちブラウザのフォームからコードをペタッと貼れるのを知らずに無意味な調査をしていた。
- functionsで動かす書き方知らなかったので、調査にやや時間がかかった
24時間で60回ほどスクレイピングする仕組みなのですが、functionsの費用がとても少なくなりそうで嬉しいです。
設置は手間かもしれませんが、定期実行する処理をfunctionsで実行し、消費リソースやコードを分割化できるのは便利に思いました。
全体を振り返って
コツコツとスクレイピングとデータ保存を繰り返してきましたが、2021年現在のGCP functionsからのGCEインスタンス内MYSQL保存が、運用者として一番安心を感じています。
開発コストもそんなに高くないと思います。
スクレイピングの2021年のベスト方法
- 最新コードと最新クラウドを掛け合わせて使うのが良い。
と思っております。
クラウドに手を出すまでは、費用面から「現在借りているGCEインスタンス内で何もかも済ませるのが節約」思想でしたが、それは間違っていました。
現在は、費用対策としてGCEインスタンス内のMYSQLを利用していますが
- クラウドfunctionsでスクレイピング
- クラウド上のデータベース
が正解なのだろうなと思っています。
これからも、スクレイピングして保存、そして表示を繰り返していくと思います、将来どんなやり方で実装しているのか楽しみですね。