著者:川嶋 宏彰
最近、プログラミング言語「Python」による自動化やデータ分析が注目されています。本特集では、Pythonと、Webブラウザを自動操作するためのライブラリ「Selenium WebDriver」を用いて、インターネットから取得できるオープンデータを例に、Webブラウザの自動操作方法およびデータ分析方法を分かりやすく紹介します。
シェルスクリプトマガジン Vol.67は以下のリンク先でご購入できます。

図4 非headlessモードのサンプルコード(sample.py)
| 1 2 3 4 5 6 7 8 9 10 11 | import time from selenium import webdriver driver = webdriver.Chrome() driver.get('https://www.google.com/') time.sleep(5) search_box = driver.find_element_by_name('q') search_box.send_keys('ChromeDriver') search_box.submit() time.sleep(5) driver.quit() | 
図7 headlessモードのサンプルコード
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | from selenium import webdriver options = webdriver.ChromeOptions() options.add_argument('--headless') options.add_argument('--disable-gpu') driver = webdriver.Chrome(options=options) driver.get('https://www.google.com/') print(driver.title) search_box = driver.find_element_by_name('q') search_box.send_keys('ChromeDriver') search_box.submit() print(driver.title) driver.save_screenshot('search_results.png') driver.quit() | 
図24 Seleniumを用いた気温データの自動取得プログラム
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | import time from pathlib import Path from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.support.select import Select # ダウンロード先フォルダの指定 dldir_path = Path('csv')  # csv という名前のフォルダとする dldir_path.mkdir(exist_ok=True)  # なければ作成 download_dir = str(dldir_path.resolve())  # 絶対パスを取得 print("download_dir: " + download_dir) options = webdriver.ChromeOptions() options.add_experimental_option('prefs', {    # Chrome のオプションに   'download.default_directory': download_dir  # 絶対パスで指定   }) driver = webdriver.Chrome(options=options) wait = WebDriverWait(driver, 10)  # 明示的待機用 (Timeout 10秒) # 自動操作開始 driver.get('https://www.data.jma.go.jp/gmd/risk/obsdl/index.php') # 「地点を選ぶ」 xpath = '//div[@class="prefecture" and text()="東京"]' time.sleep(2) driver.find_element_by_xpath(xpath).click() xpath = '//div[@class="station" and contains(@title, "地点名:東京")]' time.sleep(2)                                # (★) driver.find_element_by_xpath(xpath).click()  # (★) # 「項目を選ぶ」 driver.find_element_by_id('elementButton').click() xpath = '//span[text()="月別値"]/preceding-sibling::input' time.sleep(2) driver.find_element_by_xpath(xpath).click() css = '#日最高気温の平均' time.sleep(2) driver.find_element_by_css_selector(css).click() # 「期間を選ぶ」 driver.find_element_by_id('periodButton').click() time.sleep(2) # <select>内の<option>要素を選択 Select(driver.find_element_by_name('iniy')).select_by_value('2010') Select(driver.find_element_by_name('inim')).select_by_value('1') time.sleep(2)  # いったん止めてみる Select(driver.find_element_by_name('endy')).select_by_value('2019') Select(driver.find_element_by_name('endm')).select_by_value('12') time.sleep(2) # 「CSVファイルをダウンロード」 driver.find_element_by_id('csvdl').click() time.sleep(2) driver.quit() | 
図27 e-StatのAPI機能を利用した家計調査データを取得するプログラム
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 | import sys import urllib import urllib.request import json import calendar import matplotlib.pyplot as plt import japanize_matplotlib  # japanize-matplotlib を使う場合 import pandas as pd from scipy import stats  url = 'https://api.e-stat.go.jp/rest/3.0/app/json/getStatsData?' app_id = '<e-Statマイページで取得したアプリケーションIDを挿入>' cat01 = '010800150' # アイスクリーム・シャーベット # cat01 = '010800130' # チョコレート # cat01 = '011100030' # ビール remove_month = 0  # 特定月を除く場合は1-12のいずれかを指定 # 指定する数字の桁数は決まっているので注意 keys = {     'appId' : app_id,     'lang' : 'J',     'statsDataId' : '0003343671',  # 家計調査データ     'metaGetFlg' : 'Y',     'cntGetFlg' : 'N',     'cdTab' : '01',  # 金額     'cdTimeFrom' : '2010000101',  # 2010年1月から     'cdTimeTo' : '2019001212',  # 2019年12月まで     'cdArea' : '00000',  # 全国     'cdCat01' : cat01,     'cdCat02' : '03'  # 二人以上世帯 } params = urllib.parse.urlencode(keys) r_obj = urllib.request.urlopen(url + params)  # データを取得 r_str = r_obj.read() res = json.loads(r_str)  # Pythonの辞書へ stats_data = res['GET_STATS_DATA']['STATISTICAL_DATA'] class_obj = stats_data['CLASS_INF']['CLASS_OBJ']  # メタ情報 if 'DATA_INF' not in stats_data:  # ['DATA_INF']が入らないときのチェック用     for co in class_obj:         if 'CLASS' not in co:             print("ERROR: Check params @id= {}, @name= {}" \                 .format(co['@id'], co['@name']))     sys.exit(1) values = stats_data['DATA_INF']['VALUE']  # 統計データの数値情報を取得 # メタ情報(CLASS_INF)から取得した品目名称を図のタイトルに使う title = [co['CLASS']['@name'] for co in class_obj if co['@id'] == 'cat01'][0] print(title) # 各要素が [年, 月, 支出金額] の2次元リストにする data = [[int(v['@time'][0:4]), int(v['@time'][6:8]), int(v['$'])] for v in values] print("n =", len(data))  # 120 = 10年 x 12カ月 # Pandasデータフレームの準備 df = pd.DataFrame(data, columns=['year', 'month', '支出(円)']) df['days'] = [calendar.monthrange(df.loc[i, 'year'], df.loc[i, 'month'])[1] for i in df.index]  # 各月の日数 df['支出(円/日)'] = df['支出(円)'] / df['days']  # 1日あたりの支出金額 df['y/m'] = df['year'].astype(str) + '/' + df['month'].astype(str)  # 結合用 # 気象庁の気温データとマージ df_jma = pd.read_csv('csv/data.csv', skiprows=5, header=None, usecols=[0,1], encoding='Shift_JIS') df_jma.columns = ['y/m', '平均最高気温(℃)'] df = pd.merge(df, df_jma, on='y/m')  # データフレームの結合 if remove_month > 0:     df = df.query('month != @remove_month')  # 特定月を除く場合 # 相関係数を計算 corr, _ = stats.pearsonr(df['平均最高気温(℃)'], df['支出(円/日)']) corr_str = "相関係数: {:2f}".format(corr) print(corr_str) # 散布図をプロット ax = df.plot(kind='scatter', x='平均最高気温(℃)', y='支出(円/日)') ax.set_title(title + ', ' + corr_str) plt.show() |