アカウント画像一括更新ツールを作ったので、紹介と学びについて
GoogleやGithubなど、様々なサービスのプロフィール情報(画像, etc)を一括更新するツール、puppeteer-account-manager を開発しました。 開発の目的や、開発から得た知見を紹介します。
リポジトリは、こちらです。 github.com
- なんで作ったの?
- それ、Gravatarで良くない?
- どうやって作ったの?
- プロフィール画像を更新するAPIは、なかったの?
- パスワードって大丈夫?
- どのサービスが対応している?
- どんな学びがあった?
- 終わりに
なんで作ったの?
GithubやTwitter、Facebookなど、Webサービスにはプロフィール画像を登録することができます。 私の性格上、どのサービスでも、同じ画像で登録したいと考えています。
そのため、いい感じのプロフィール写真を手に入れたら、全サービスのプロフィール画像を再登録しないと気がすまなくなり、とても面倒です。 そこで、今回、その面倒さを解決したく、このツールを作りました。
それ、Gravatarで良くない?
今回の面倒さは、GravatarというWebサービスで解決できるかもしれません。
このサービスは、グローバルなプロフィール画像を提供するサービスです。 API経由で、プロフィール画像を取得できます。
しかし、次の問題があったので、却下となりました。
- gravatarが提供するプロフィール画像サイズは80px × 80px
- サービスによっては、小さすぎる
- 画像サイズを拡大することができるが、画質がよくない
- サービスによっては、小さすぎる
- gravatarが提供するプロフィール項目が固定
- 画像だけではなく、プロフィール項目も一括登録したかった
- サービスによっては、プロフィール項目がマッチしない
- 画像だけではなく、プロフィール項目も一括登録したかった
そこで、Contentful というAPIベースのCMSを使うことにしました。
Contentfulでは、自由に項目を決めることができます。 独自に作った項目 (画像や紹介文)を、API経由で取得できるため、とても便利です。
どうやって作ったの?
愚直なやり方です。 Puppeteerと呼ばれる Chromeブラウザを自動操作できるライブラリを使いました。 Chromeブラウザから、"各サービスへログインし、写真をアップロードする"処理を自動化しただけです。
プロフィール画像を更新するAPIは、なかったの?
サービスによってはあります。例えば、Twitterには、次のようなプロフィール画像を更新するAPIがあります。
ただ、全てのサービスには、そのようなAPIはありません。 APIを使って更新するのが正しい姿ですが、全サービスの実装方法の足並みを揃えるために、 Puppeteer で自動操作することにしました。
パスワードって大丈夫?
Puppeteerを動かすnodeアプリケーションと、Chromeブラウザを同一マシン内で動作するようにしました。 そのため、nodeアプリケーション実行中に、パスワードを傍受されることはありません。 また、パスワードの設定は環境変数から注入するようにしています。 Dockerコンテナで動作できるようにしているので、ローカルでも、コンテナサービスでも動かすことができます。
今後、パスワードの管理は、KeepassやLastpassのようなサービスと連携したいと思っています。
どのサービスが対応している?
対応サービスは次のとおりです。
詳しくは、 https://github.com/Silver-birder/puppeteer-account-manager/blob/master/src/index.ts をご確認下さい。
どんな学びがあった?
結構色々とハマりました。
極力 セレクタ指定したコードを書かない
Webサービスが返すHTMLは、いつもずっと変わらないことはありません。 あるidやclassのhtmlタグがずっと残り続けるとは限りません。
そこで、できる限り、セレクタを指定せずにブラウザ操作をするようにしました。 例えば、
- ボタンやリンクをクリックしてページ遷移するのではなく、目的のページへ最短で直接遷移する
- submitボタンをクリックするのではなく、エンターキーを入力する
です。こうすることで、安定した自動化ができました。
XPathが意外と使える
GoogleやMediumでは、idやclassがランダム値になっています。 そのため、単純なidやclassを指定して進めることができません。
そこで、『○○』のテキストが含まれているセレクタの指定することが、XPathでできます。 これは、助かりました。
ログインが難しいものは、無理せず諦める
Amazonのログインは、2段階認証が発生します。 テキストメッセージや、音声電話によるログインが求められ、Puppeteer単体ではどうしようもありません。
この2段階認証の機能を解除することもできますが、セキュリティ上よろしくないので、ここは無理せず諦めることにしました。
並列処理をガンガン実行する
処理速度向上のため、全サービスを Promise.allで並列処理しました。それぞれが、シークレットウィンドウで開くことで、独立して処理するようにもしました。 しかし、たまにPuppeteerが落ちてしまうことがあります。原因は、実行しているマシンのスペック(Core数)にも影響しますが、サービス側からの影響も受けたりします。 そのため、落ちても大丈夫のようにエラーハンドリングし、リトライするようにしました。
また、失敗したらどういった画面なのか知りたいので、スクリーンショットを撮るようにもしました。
Docker で実行可能に
Puppeteerに必要なモジュールをDockerに詰め込み、ログイン情報等を環境変数から外注することで、 環境非依存の実行環境ができました。そのため、Pub/SubとContainer Engine等を組み合わせれば、 ContentfulのWebfook経由で、アカウント情報を更新することができます。
終わりに
私の性格がもっと大雑把であれば、このツールを作らなかったのですが、どうしても気になって仕方がなく... (笑) 最後まで読んでいただき、ありがとうございました。