著者:川嶋 宏彰
最近、プログラミング言語「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() |