PyCon JP 2022

Your locale preferences have been saved. We like to think that we have excellent support for English in pretalx, but if you encounter issues or errors, please contact us!

業務改善の面白さ ~毎日更新されるビジュアルコンテンツの差分をわかりやすくするためのプロトタイプを作るまで~
2022-10-14 , pyconjp_5
Language: 日本語

課題の背景

日本経済新聞社では、日々報道機関としてニュースを配信している。その中でも定期的にデータを更新する「チャートで見る日本の接種状況 コロナワクチン」コンテンツがある。このコンテンツは 特に人の健康や生命に関わる大事な情報であるため、データの間違いや表示の間違いは許されない。

課題

記者チームが公開されるデータに責任を持っている。
記者側がスプレッドシート上でデータを確認していたとしても、実際にWebページ上で正しく更新されているかは、いちいちページにアクセスして見ないと確認できない状態だった。

解決手段

そこで、ビジュアルリグレッションテストのように、何が画面に変更があればその差分をわかりやすく並べ表示することで、それが意図された変更なのかが誰でも判別することができる状態を目指せるのではないかと考えプロタイプを作ってみた。


技術的な要件

前提

表示されるデータは記者が責任を持つ。記者が管理しやすいスプレッドシートにデータが集まっている。
このコンテンツは、スプレッドシートのデータをコンテンツに表示している

要件

聞き取りをして考えた要件は下記となった
- 記者チーム側がデータを更新するときに、前の状態と今の状態とその差分が表示されると良い
- 記者チームやディレクターやエンジニアやデザイナー職種問わず、誰もがその差分を確認することができる
- 連絡手段にSlackを利用しているので、その結果をSlackにまとめられるとよい

検討したこと

reg-suitを利用して、CIに乗せてシステムを起動する

reg-suitを用いた流れとしては、下記のようにできればと考えた
- GitHubにpushすると、CircleCI上でPuppeteerを動かし、スクリーンショットを撮影し指定したフォルダに収める。
- そのフォルダをreg-suitで指定すると、reg-suit側で指定したS3に、静的サイトとしてアップロードされる。
- それが完了すると、GitHubのコメントに通知が飛ぶ。

Puppeteerで、スクリーンショットを撮影するコードは自分で書く必要はあるが、まさしく、これが欲しかった!がまとまったツールだ。しかし、このように便利なreg-suitですが、このプロジェクトでは利用できなかった。

このページは、前項でも記述したとおり、2つのチームの成果物から成り立つ。 一つはGitHubで管理しているリソース、もう一つは記者チームがチェックしているスプレッドシートのデータである。

reg-suitでは、GitHubで管理しているリソースの範囲内であれば、スクリーンショットを取得して差分を比較することはできるが、本番環境に反映されるデータ自体は反映されていない。 本当に差分を比較したいのは、本番環境で表示されているものと、過去表示されたものである。
また、レポートの通知自体もGitHubのアカウントを持っていないと確認できず記者チームにとっては負担になる。差分をさっと見たいのにクリック数が多いなどの要件に対する不備もあった。よって、reg-suitでは実現できないという判断をした。 こうなると残された手段は、自作するしかなかった。

差分を検出して、Slackに投下するしくみ

利用したツール

  • CircleCI
  • Python3
  • スクリーンショット撮影:selenium :webdriver-manager
  • S3にアップロード :Boto3 :python-dotenv
  • 画像加工: opencv-python: NumPy
  • Slack通知: Python Slack SDK

実行方法を決める

記者チームが、データの更新を行った後にすぐに差分を撮影して、自動で投稿するのがベストではあるが、時間がかかりそうだった。今回は、早めにプロトタイプを作って便利か検証したかったので、データの整形が終わり本番反映される時間帯の後である毎日17時頃に、CirlceCIで定期実行するように設定した。

比較画像を用意する

CircleCI上でブラウザをheadlessモード(バックグラウンドで動くモード)で立ち上げてページを表示し、スクリーンショットを取る。 次に、S3にアップロードしてある、前回変更時に撮影した画像をダウンロードしておく。

画像の高さを揃えて、比較や加工しやすくする

改修作業がはいると大幅にページの高さが変わる可能性がある。そのページの高さの変更に備えて、現在のページのスクショと過去のページのスクショの高さを揃えるようにOpenCVで足りない高さ分白画像を追加する。

画像の差分を検出するための準備をする

OpenCVで画像の差分を比較し、差分マスクを作成する。
差分マスクだけだと、何もわからないので、画像を暗くしてマスクと重ね差分が明確になるように合成した。

画像の差分を検出し、差分があれば作成したスクリーンショットをS3にアップロードする

作成したマスク画像から、白色ピクセル数を算出し、白色の部分が全体のどれくらいの割合を占めているのかを計算する。計算式は 白色ピクセル数/画面ピクセル数 とした。今回はなにか少しでも変化があれば変更だとみなしたため、 白色ピクセル数/画面ピクセル数>0 であれば変更として検知した。

変更を検知しなかった場合は、ここで処理を終了します。 変更を検知した場合は、S3に今回撮影した画像をアップロードし、次回の検出で用いるようにした。

Slack投稿用に画像を合成する

変更を検知した場合、Slack投稿用に変化後、変化前、差分の3種類の画像を並べて合成する。ここでまとめた理由はSlackで画像をクリックしたときに、一画面でまとめて見ることができるようにするためである。

Slackに投稿する

最後に、files.uploadAPIでSlackに画像とともに通知します。 Slackには下記のように、投稿する事ができた。
この画像をクリックすると、左側から「変更後」「変更前」「差分」を一覧で見ることができるようになった。 Slackからワンクリックで、差分の変更を見られるようになり、reg-suitよりも少ない手数で目的を達成することができた。

導入後の声

記者の方からのコメントとしては、「便利な仕組みをありがとうございます」という声をいただいた。
ディレクターやデザイナーからのコメントとしては「明らかにおかしい箇所がないか簡単に判別できるのはありがたいです。
特にデザイナーの視点からだと、データの桁数によってレイアウトが変わる要素があるので、意図していないレイアウトになっていないかが一目で分かるのが良いです」だった。

伝えたいこと

記者、デザイナー、エンジニアと3つの職種が協力しながらコンテンツを作成している環境にいて得た知見は、「何に困っているのか、どうなったら便利なのかを聞いても、それぞれの職域の範囲内しか返答ができない場合がある」ことだ。
誰かの課題を解決して、価値が生まれる。特にエンジニアは技術を使って困りごとを解決できる職種である。
エンジニアが活躍できる改善の種は、身近にあるのではないだろうか?
まずは隣の人の話を聞いてみたり話してみることろからスタートするとよいのではないだろうか。

Developer
Data visualization