コロナの拡大状況を知りたい！そんなサービスをFlask,Vueで作ってみた

> 2021/09/26 こちらの記事で作成・公開していたサイトは既に閉鎖となっています。
> 記事自体は備忘録的に残しておきますが、ご理解のほどよろしくお願いします。


コロナが世間を賑わせてから厚労省が感染者の情報を公開しています。その情報をスクレイピングしてグラフ化するサービス「[**データで見る新型コロナの拡大**](https://covid19.hpspider.online/)」を作ってみました。
[<img width=６00 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65735/6545c5f2-aaa2-d0ef-d639-ffddf0be304d.png">](https://covid19.hpspider.online/)

## ことはじめ

私は仕事で医療系システムの開発に従事しており、コロナの拡大状況は非常に興味がありました。ニュースメディアでは断片的な情報だったり見辛かったりしたので、本サービスの作成に至りました。


## 開発環境

- サーバーサイド：python/Flask, Scrapy, gunicorn, apache2, Postgres
- フロントエンド：vue.js vue-chart.js vue-good-table


## 作り方

> 作成の手順とその際に参考にしたサイトのリンクです

### 1) 最初に厚労省のページを確認

厚労省のページとそのソースを見て、「_これならスクレイピングできるな_」というアタリを見定めました。欲しい情報の書かれたHTMLソースを並べて共通点を見つけていく感じです。

- [新型コロナウイルス感染症に関する報道発表資料（発生状況、国内の患者発生、海外の状況、その他）](https://www.mhlw.go.jp/stf/seisakunitsuite/bunya/0000121431_00086.html)

### 2) Scrapyを使ってページをスクレイピング

ターゲットとなるページには欲しい情報がtableタグで記載されていたので、Pandasのread_htmlメソッドが重宝しました。read_htmlメソッドを使うと、tableデータの内容だけがDataFrameのリストで取得できます。

スクレイピングしたデータはPostgresに突っ込みます。
なお、取得したデータはCSVファイルとしてローカルディスクにも保存するようにしました。これはデータが後々膨らんだ時にファイルとして残っている方が拡張しやすいと個人的に感じてるからです。

- [Scrapyチュートリアル](https://doc-ja-scrapy.readthedocs.io/ja/latest/intro/tutorial.html)
- [pandas read_html](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.read_html.html)
- [Python, pandasでwebページの表（htmlのtable）をスクレイピング](https://note.nkmk.me/python-pandas-web-html-table-scraping/)

### 3) フロントエンドの準備

Flaskを使って画面表示するページの作成を開始します。vue.jsとvue-chart.jsを使いたかったので、作業効率化のためにWebpackも導入しておきます。

- [Flaskへ ようこそ](https://a2c.bitbucket.io/flask/)
- [はじめてのWebpack](https://qiita.com/cheez921/items/266b1b4534b6111a9686)
- [npmとpackage.json](https://qiita.com/Sekky0905/items/452619651cdd950c2271)

### 4) APIとフロントエンドをガリガリ書く

APIとフロントエンドの開発を同時進行で行います。

APIの開発では、まずPostgresにコンソールでログインして欲しい結果を得れるクエリを精査します。満足するクエリが出来たらその結果をAPIの出力として返すようにFlaskで実装していきます。RESTにする必要はなかったのでFlask-APIは使わずに普通にJSONデータを返すだけの実装になりました。

フロントエンドはaxiosを使ってAPIからのレスポンスを受け、その結果をvue-chart.jsで作ったコンポーネントに渡して表示させます。

- [Vue.js](https://jp.vuejs.org/index.html)
- [aixos](https://github.com/axios/axios)
- [vue-chartjs](https://vue-chartjs.org/)
- [chart.jsで積み上げ横棒グラフを描く](https://qiita.com/yuba99/items/0442828b876dec67162a)
- [vue-good-table](https://xaksis.github.io/vue-good-table/)

### 5) サーバーにデプロイして公開

サーバーにプログラムを設置してgunicornで8001番ポートでデーモン起動するようにします。ドメインを設定してApache2にヴァーチャルドメインの設定をしたら後段の8001番ポートにリバースプロキシするようします。
なお今回nginxでなくApache２を使った理由は、すでにApache2で稼働しているサイトがあり面倒だからそのまま使ったに過ぎません。またドメインにお金をかけたくなかったので、以前から使っていたドメインにサブドメインを追加設定しました。

最後にcronでデイリーでスクレイピングするように設定すれば完了です。

- [gunicorn + Flask + nginx + Systemdで動かしてみた](https://qiita.com/arata-honda/items/09e1c350b1bd8a186e9c)
- [gunicorn configuration](http://docs.gunicorn.org/en/latest/configure.html)

## 所感など

- 本サービスを作るにあたり多数のサイトを参考にさせていただきました。ページ内でリンクを貼ったサイトはもちろん、他にも多数の有益な情報を公開している皆様に感謝です。

- 技術的なチャレンジとして、今回初めてFlaskを使ってみました。非常に簡単で使いやすいフレームワークだと思ったので今後も活用していきたいです。

- サービスを作ってから気づいたけど、コロナ感染者の情報が厚労省以外にもいくつか出ていてそれぞれ値が違ったりする。（例：[都内の感染者動向](https://stopcovid19.metro.tokyo.lg.jp/) < 厚労省の発表してる東京都の情報と異なる）。どれが一次情報として適当なのだろう？？




最後に、、
サービスを開発する上での技術的な問題だけでなく、医療やヘルスケアの視点からもアドバイスなど頂ければ大変嬉しいです。
何卒よろしくお願いします。