((7回目の出直し🌼))

好きなことを自分のペースで、のんびり更新

ブログ管理画面のサマリーとアクセス解析を自動でキャプチャーする

ひさしぶりにがっつりプログラムをした3連休でした。

f:id:kanaxx43:20210920155301p:plain

困っていたこと

はてなのアクセス解析とトップページの数値って、過去になるとわからなくなるんですよね。

こことか、
f:id:kanaxx43:20210920141655p:plain:w400

こことか
f:id:kanaxx43:20210920141657p:plain:w400

月末に振り返りをするときに、数値がなくなってしまうと二度と取れないのです。月末の最終日にPCに張り付いてスクショをとるしかないわけです。
人間がPCと時間に縛られるのは悲しい。

ということで、自動でスクショをとる工夫をします。

作ったもの

はてなブログ管理画面の2つのページのスクショを自動でとるスクリプトです。 左ナビと上部のヘッダーを除外したエリアをキャプチャーします。

  • はてなのサマリーの数値
  • はてなのアクセス解析のページ

撮ったスクショ画像に日付を入れてCloudinaryにアップロードします。

今回は、はてなブログを題材にしましたが、ブラウザを自動操作してキャプチャーをとる仕組みなのでいろいろと応用が効くと思います。

実際の作成した画像

こんな感じです。

f:id:kanaxx43:20210920141421p:plain f:id:kanaxx43:20210920141256p:plain

これを毎日、自動で保存していきます。

動作の設計

今回は、node.js(Javascript)で作られたバッチプログラムです。画面はありません。

処理の流れは、

  • 実行すると、はてなブログの管理画面にログインします。(ログインのIDとパスワードが必要です)
  • ログインしたあとは、管理画面のトップページのサマリー部分のキャプチャーをとります。
  • そのあと、アクセス解析のページに遷移をしてアクセス解析のグラフ周辺をキャプチャーします。
  • キャプチャーしたものをCloudinaryにアップロードします。transformationパラメータをセットすることで変換しつつアップロードできます。

CloudinaryはHeroku対策です。
Herokuを使うと自分で作ったファイルを置いておくことができず、再起動のタイミングで捨てられてしまします。作ったらすぐに外部ストレージに飛ばしておかないといけません。

せっかくなので、Cloudinaryの文字オーバーレイの仕組みを活用して撮影日を画像に書き込んでいます。

ちなみに、Windows環境で動かすだけならCloudinaryはなくても大丈夫です。

使ったもの

いつもどおりWindows環境で開発しました。

  • Windows10
  • node.js (v16.9.1)
  • puppeteer
  • Cloudinary (node.js SDK)

最終動作環境はHerokuの予定です。

コード

コードはこちらに置いてあります。100行くらいです。
https://github.com/kanaxx/hatena-autocapture

ローカルでの動かし方

簡単に動かし方をかいておきます。

# コード持ってくる(必要なのは2つだけ)
git clone git@github.com:kanaxx/hatena-autocapture.git

# モジュールをインストール
cd hatena-autocaputure
npm install

# 環境変数の設定
set hatena_id=
set hatena_pass=
set blog_admin_url=
set CLOUDINARY_URL=cloudinary://

# 実行
node hatena-autocapture.js

ログがたらたら出て終わります

完了すると、capturesフォルダにファイルが出来上がります。
f:id:kanaxx43:20210920152008p:plain

環境変数

4つ必要な設定があるのでsetコマンドでセットする

変数名 内容
hatena_id ログイン用のID。はてなIDでもメールアドレスでもOK
hatena_pass パスワード
blog_admin_url ブログ管理画面のトップページURL。最後のスラッシュまで*1
CLOUDINARY_URL Cloudinaryの環境変数。
CLOUDINARY_URL=cloudinary://xxx:yyy@zzz*2

はまったところ

ネットを調べながら作りましたが、日本語の資料も充実していたので、プログラム自体はそんなに難しくなかったです。 初めてPupetterを使ってので、少しだけハマりどころがありましたのでメモしておきます。

ログインができなった

はてなへの最初のログイン部分がうまくいきませんでした。Windows上で動かすとうまくいったのに、Herokuで動かすと全くといっていいほどうまくいかなかったです。

仮説ではあるのですけど、

  • UserAgentを指定していなかったので、機械的なアクセスとみなされた
  • 日本国外のIPアドレスからのアクセスだった怪しまれた

IPアドレスは変更できないので、ダメ元でUserAgentを明示的に付けてみたら、うまくいきました。謎です。

await page.setUserAgent(
 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36
');

そんなこともあるんだ。まぁ、そんなもんです。

サイトが英語表記になる

Herokuからアクセスしてみたら、ログイン画面が英語で返ってきました。
普段使っているブラウザが日本語設定なので、日本人がこの現象に出くわすことは少ないですが、スクショをとってみたら英語だったので驚きました。

f:id:kanaxx43:20210920150437p:plain 英語表記のはてなアクセス解析画面

はてなブログも複数言語のユーザを想定して外国語対応をしていたわけですね。知りませんでした。

おそらくAccept-Languageの設定を見て出し分けているのだろうと思い、以下の2か所に指定したら上手くいきました。

Puppeteerの起動オプションに言語を指定

//puppeteerのlaunchにlangオプションを指定
args: ['--no-sandbox', '--disable-setuid-sandbox', '--lang=ja-JP,ja'],
リクエストヘッダーに日本語を指定
//Accept-Languageヘッダーとユーザエージェントを指定
await page.setExtraHTTPHeaders({'Accept-Language': 'ja'});
  

キャプチャーが取れたり取れなかったり

完全に表示するまえにキャプチャーとっちゃってるときがある。無駄にスリープする感じにしたら、今のところうまくいった。

(マニュアルを読む限り、この指定はいらないみたいだけど)

  await page.waitForTimeout(1000);

たまにログインが失敗する

いつもなるわけじゃないんですけど、ログイン失敗することがあります。スクショがこの画面になりました。
f:id:kanaxx43:20210920151823p:plain

理由は不明だけど、はてな側の不正ログイン対策ですね。機械的なログインを何らかの判断基準によって弾いていると。

当初は完全に諦めていましたが、5回くらいログインを繰り返すようにプログラムを修正しました。5回やってダメだったらその日は諦めるロジックにしました。

ログインユーザを分離しておく対策

このスクリプトは、はてなにログインするために「ログインID」と「パスワード」を使います。

プログラム上に書く必要はないですが、システムのどこかに設定するということは、わずかにでも漏洩する可能性が発生します。 自分がメインで使っている「はてなID」と「パスワード」が漏れる大変です。急いでパスワードを変更しなくてはいけせんし、はてなの他のサービスを乗っ取られることになります。

メインアカウントだとブログ管理者になれてしまうので、ブログを丸ごと削除できてしまいます。 そうなるとと被害が甚大です。

そのための対策を少々しておきます。

完璧な対応ではないです。何かあったときの被害を最小に抑える対応です。

ブログメンバーの追加

はてなブログには「ブログメンバー」機能があります。他のはてなユーザを管理画面にアクセスできるようにし、共同編集ができる機能です。
f:id:kanaxx43:20210923103655p:plain

この機能を使って、メインとは別のユーザ(サブ)を追加しておきます。サブのIDとパスワードでプログラムを動かすようにします。
仮に何か良くないことが起きていた場合には、ブログメンバーから外すだけでブログ管理画面にログイン不可にできます。

f:id:kanaxx43:20210920152549p:plain

追加メンバーには「管理者」、「編集者」、「寄稿者」と3つの設定があります。 試したところ、今回の作業に必要なブログトップとアクセス解析を見るためには、少なくとも編集者である必要がありました

なので編集者で登録しておきます。

はてなサブアカウントの追加

ブログメンバーに追加する際に、共同編集者の「はてなID」を指定する必要があります。
はてなIDを複数作ることもできますが、自分のメインアカウントの下にサブアカウントをぶら下げることができるので、それで対応します。

f:id:kanaxx43:20210920153227p:plain

サブアカウントは5つまで作れるので、うまいこと使いわけてください。

さいごに

HeadlessブラウザであるPuppeteerを初めて使ってみました。 プログラムでブラウザを動かすのは大変だと思っていましたが、それほど難しくなかったですね。環境構築も難しくなかったです。

ただ、ブラウザをプログラム側から動かすので、どうしても癖というやコツが必要になります。その辺は慣れていくしかないんでしょうね。

今回はWindowsで動作確認まで。次回はHerokuに乗っけてガンガン回していく予定です。

参考にしたページ

ヘッドレス Chrome Node API 「Puppeteer」
https://qiita.com/bezeklik/items/c6448d50ff0efb45829e

HerokuにPuppeteerの実行環境を構築する
https://qiita.com/jerrywdlee/items/ffc988956eb75a99bc3c

はてなブログで「サブアカウントの作り方」
https://www.elppar.com/un-hatena-subaccount

*1:https://blog.hatena.ne.jp/kanaxx43/kanaxx.hatenablog.jp/

*2:Cloudinaryのダッシュボードに表示されているやつ
f:id:kanaxx43:20210920145314p:plain