Blog
Blog

Blog

Pythonスクレイピングとthree.jsで実現するデータビジュアライゼーション

2020年4月03日

haino

こんにちは。クリエーターの灰野です。世界的に猛威を振るう新型コロナウイルス(COVID-19)の患者数と死亡者数が毎日のように増加していますが、今後のさらなる悪化が心配されますね。そのような状況の中、政府や東京都の要請を真剣に受け止め、弊社も先月末より出社の必要性がない場合は、全社員がテレワークにて仕事を行えるよう環境を整え業務を行なっています。長期的な経済への影響も心配される中、私個人としても世界を取り巻くこのような事態が早く終息してほしいと願っています。

さて今回は、業務の空き時間を利用して、今後さらなる蔓延が懸念される新型コロナウイルス(COVID-19)の患者数のデータビジュアライゼーション・コンテンツの制作に取り組んでみました。今回制作したコンテンツは下記のURLにてご覧いただけます。※現状ではPCのみで、ブラウザはChrome推奨です。
https://axel.co.jp/covid19/

このコンテンツは個人的に興味のあったPythonスクレイピングとthree.jsへの理解を深める目的で制作してみたのですが、新型コロナウイルス(COVID-19)の患者数をthree.jsで描画する3Dの地球儀にデータをマッピングするため、主に二つのデータが必要となりました。一つは国別の患者数、そしてもう一つは国別の緯度経度情報です。

一つ目の国別の患者数は「WHO」にて毎日更新されていたので、それを利用させていただきました。※1

二つ目の国別の緯度経度情報は「Geocoding」というサイトを利用させていただきました。※2

追記:2020年4月7日以降の患者数はWikipediaの「2019–20 coronavirus pandemic by country and territory」より取得させていただきました。※3

Pythonにて行う二種類のスクレイピング手法

Pythonはスクレイピングを行う点でも非常に優れた言語です。PythonによるスクレイピングではBeautifulSoupライブラリを使うのが最も一般的です。短いコード量でサイトのコンテンツを拾うことが可能です。しかしBeautifulSoupも万能ではなく、Ajaxで出力されているhtml等は拾うことができません。今回スクレイピングを実施したWHOのコンテンツはまさにこれに該当したため、BeautifulSoupとは異なる手法を利用せざるを得ませんでした。その手法とは、Seleniumライブラリを使ってChromeを自動制御するスクレイピングです。

BeautifulSoupを使ったスクレイピングは以前にも実装した経験があったのですが、Seleniumを使った手法は今回初めてでしたので、この場を借りてその手法を一部公開したいと思います。

まずは、pipにてSelenium及び、Chormeを制御するchromedriver-binaryをインストールします。

pip3 install selenium
pip3 install chromedriver-binary==バージョン番号

この時に注意する必要があるのが、スクレイピングを実施するPC(サーバー)にインストールされているChromeのバージョンとchromedriverのバージョンを合わせる必要があるという点です。自分の場合は、Macを使ってスクレイピングを実施しましたが、インストールされているバージョンが「80.0.3987.149」だったので、chromedriver-binaryのバージョンは「80.0.3987.106.0」を選ぶことにしました。

pip3 install chromedriver-binary==80.0.3987.106.0

chromedriverの場合、マイナーバージョンまで全て揃っているわけではないのですが、バージョンが最も近いものを選べば動作するようです。

自分のPCにあったバージョンはこちらのサイトで確認することができます。
https://sites.google.com/a/chromium.org/chromedriver/

では、サンプルコードです。

# -*- coding: utf-8 -*-
import traceback
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
import chromedriver_binary
import time

# 抽出データ初期化
item = ''

options = Options()
# ヘッドレスモードで実行する場合
# options.add_argument("--headless")
driver = webdriver.Chrome(options=options)

try:
    # 読み込み先URL
    driver.get("___任意のURL___")

    # コンテンツが描画されるまで待機
    time.sleep(30)

    # 対象を抽出
    elem_list = driver.find_elements_by_class_name("___任意のclass名___")

    for elem in elem_list:
        # 該当データを抽出して出力
        if str(elem.text) != '':
            value = str(elem.text)
            # 必要に応じてelem.textを加工する
            item += value + '\n'
finally:
    # ブラウザを閉じる
    driver.quit()

print(item)

大体、こんな感じのコードで目的のコンテンツを取得できると思います。
プログラムを実行すると、実際にChromeが起動して、テキストを拾い上げてくれるはずです。終わればChromeは自動的に終了します。

今回制作したコンテンツは、このような手法でWHOにて公開されている患者数のデータを一旦csvに落とし込み、次いでGeocodingというサイトへアクセスし、BeautifulSoupにてその国の緯度経度を取得するためのコードを別途用意しました。

ただ、その都度BeautifulSoupでスクレイピングするのも効率が悪いですし、取得先のサイトにも無駄な負荷をかけることになるので、初回のみ全ての国の緯度経度の取得を試み、二度目以降は、新たに患者が発生した国の差分のみ、スクレイピングで緯度経度を取得するような仕様で実装しました。データを取得するコードが用意できたら、あとはcron等で自動化すれば毎日自動でコンテンツを更新させることができます。

データビジュアライゼーションの奥深さ

データを可視化すると直感的にデータを把握できるので、大変興味深いですよね。数字を追うだけでは気付けないデータの推移や変化、相対的な差異にもすぐに気づく事ができるのです。

今回データビジュアライゼーションの要として利用したのは、弊社のトップページにも使用しているthree.jsライブラリをラッピングしたGoogle Creative Labによる「WebGL Globe」というライブラリです。基本的に3D地球儀の部分はこのライブラリが描画してくれるので、実装はそれほど難しくありません。マッピングしたいデータを所定のjson形式に落とし込んで読み込ませればOKです。「WebGL Globe」は大変よくできたライブラリですが、最近は全く更新されておらず、細部に若干詰めの甘さが感じられたので、独自にブラッシュアップしました。また色やデザイン等は、今回のコンテンツに合わせてカスタマイズしています。「WebGL Globe」は古いライブラリではありますが、地球規模のデータをマッピングするにはまだまだ使えるのではないでしょうか。なお、地球儀のテクスチャは、NASAにて公開されている画像データの中からちょうど良いものを選び、色調などを独自に改変したものを利用させていただきました。

今回は、世界中に蔓延している新型コロナウイルス(COVID-19)の患者数データを3D地球儀にマッピングしてビジュアル化するコンテンツを作ってみましたが、いかがだったでしょうか。

現状としては、スマホへの最適化が完了しておらず、国名や国ごとの感染者数も分からないなどの改善すべきと思われる点も多々ありますが、それらの点は、近日中に改善を図りたいと考えています。

待ちに待ったオリンピンクイヤーに、100年に一度の世界的なパンデミックが発生するなんて、誰も予想してませんでしたよね。今回の新型コロナウイルス(COVID-19)の流行は、日本のみならず世界的な経済への影響も深刻化が懸念されています。一日も早い終息を願うばかりです。

弊社としては、ただただ新型コロナウイルス(COVID-19)に負けないよう日々の業務をこなしつつ、リッチなウェブ・コンテンツの表現、新しい分野への挑戦を今後も追求していくのみと感じています。

引き続き、皆様からのお仕事のご相談をお待ちしております!

※1 WHOのサイトにて公開されている記事は「CC BY 3.0」または「CC BY-NC 3.0」によるライセンスに準拠するとのことでしたので、コンテンツには著作権帰属表示を表示しました。またサイトを調べた感じでは、スクレイピングは禁止されておらず、当方が必要とした一日に一回のスクレイピングの実施は問題ないであろうと判断しました。
https://www.who.int/about/who-we-are/publishing-policies/copyright

※2 アクセスを10秒程度に1回のアクセスに限定する旨の規約があったので、それに則った手法にて実施しました。

※3 2020年4月7日よりWHOのデータ公開方法が変わったため、それ以降はWikipediaの「2019–20 coronavirus pandemic by country and territory」より患者数のデータを転載させていただいております。Wikipediaのライセンスは「CC-BY-SA 3.0」に準拠しており、当方もそれに則りコンテンツ内に著作権帰属表示をしています。