見出し画像

[Python] Selenium サイトからCSVファイルをダウンロードするツールを作る 6~CSVファイルのデータをSqliteでDBに登録する

はじめに

前回は、Python+Seleniumで、WebページからCSVファイルをダウンロードし、ダウンロードしたCSVファイルを読み込んで、Pandasを使って必要なデータの抽出する処理を追加しました。

今回は、ダウンロードしたCSVファイルから抽出したデータを、データベースに登録する処理を追加します。

使用するデータベースは、Pythonの標準ライブラリにある、SQLiteを使用します。

使用するライブラリ

SQLite3

標準ライブラリ内にある、SQLiteのデータベース用ライブラリ。

動作環境

・windows10
・Python 3.7.6
・Chrome バージョン: 87.0.4280.141

実装

from selenium import webdriver
from selenium.webdriver import ChromeOptions
import os
import glob
import time
import pandas as pd
import sqlite3

downloadsFilePath = 'downloads'

# Selenium初期化
def initialize():
options = webdriver.ChromeOptions()
prefs = {
   "download.default_directory": path,
}
options.add_experimental_option("prefs", prefs)
driver_file = r'C:\Users\XXXXX\Documents\webdriver\chromedriver.exe' # ドライバのPathを設定
return webdriver.Chrome(driver_file,options=options)

# 指定したフォルダの最新のファイルパスを取得する
def get_latest_file_path(path):
file_path = ''
if len(os.listdir(path)) != 0:
   file_path = max (
       [ os.path.join(path, f) for f in os.listdir(path)], 
       key = os.path.getctime
   )

return file_path

# 指定フォルダに、ファイルのダウンロードが完了するまで待機する
def wait_file_download(path):
# 待機タイムアウト時間(秒)設定
timeout_second = 10

# 指定時間分待機
for i in range(timeout_second + 1):
    # ファイル一覧取得
    match_file_path = os.path.join(path,'*.*')
    files = glob.glob(match_file_path)

    # ファイルが存在する場合
    if files:
        # ファイル名の拡張子に、'.crdownload'が含むかを確認
        extensions = [file_name for file_name in files if '.crdownload' in os.path.splitext(file_name)]

        # '.crdownload'が見つからなかったら抜ける
        if not extensions : break

    # 指定時間待っても .crdownload 以外のファイルが確認できない場合 エラー
    if i >= timeout_second:
        # 終了処理
        raise Exception('Csv file cannnot be finished downloading!')

    # 一秒待つ
    time.sleep(1)

return

URL = 'https://www.data.jma.go.jp/obd/stats/data/mdrr/docs/csv_dl_format_mxtem.html'

browser = initialize()
browser.implicitly_wait(10)

# ブラウザでurlを開く
browser.get(URL)

# csvファイルをダウンロード
element = browser.find_element_by_partial_link_text('ダウンロード(最高気温)')
element.click()

# Chromeのダウンロード先に指定したパスを取得
path = os.path.join(os.getcwd(), downloadsFilePath)

# csvダウンロード完了まで処理を待たせる
try:
wait_file_download(path)
except Exception:
sys.exit()

browser.close()
browser.quit()

# ダウンロードしたフォルダから最新のファイルを取得
file_path = get_latest_file_path(path)

# csvファイル読み込み
df = pd.read_csv(file_path,encoding='shift_jis')

# ①特定行を抽出
df_pref = df[df['都道府県'].str.contains('北海道|沖縄県')]

# ②列を追加(年、月、日に分かれているデータを日付型に変換し、新規で、日付の列を追加
date = datetime.date(df.loc[0, '現在時刻(年)'],df.loc[0, '現在時刻(月)'],df.loc[0, '現在時刻(日)'])
df_pref['日付'] = date

# ③特定列を抽出
# 日付、都道府県、地点、今日の最高気温を抽出
df_data = df_pref[['日付','都道府県','地点','今日の最高気温(℃)']]

# 「weather.db」に接続(自動コミットする)
conn = sqlite3.connect('weather.db',isolation_level=None)

# カーソル取得
cur = conn.cursor()

for index, row in df_data.iterrows():
 sql = f"INSERT INTO HiTemp values(null,'{row['日付']}', '{row['都道府県']}', '{row['地点']}', '{row['今日の最高気温(℃)']}');"
 cur.execute(sql)

# データベースを閉じる
conn.close()

追加した処理は、DB登録の処理です。

# 「weather.db」に接続(自動コミットする)
conn = sqlite3.connect('weather.db',isolation_level=None)

DBに接続する処理です。
指定したファイルがない場合は、新規作成、存在する場合は、指定データベースを開きます。

# カーソル取得
cur = conn.cursor()

for index, row in df_data.iterrows():
 sql = f"INSERT INTO HiTemp values(null,'{row['日付']}', '{row['都道府県']}', '{row['地点']}', '{row['今日の最高気温(℃)']}');"
 cur.execute(sql)

カーソルを取得して、データを登録するSQL文を実行しています。

# データベースを閉じる
conn.close()

DBの接続を終了する処理です。接続と終了はセットで使用します。

登録したデータを表示した結果は下記です。

スクリーンショット 2021-01-20 082315


まとめ

今回は、Python+Seleniumで、WebページからCSVファイルをダウンロードし、ダウンロードしたCSVファイルを読み込んで、Pandasを使って必要なデータの抽出し、データベースへ登録する処理を追加する処理をお伝えしました。こちらでツールは完成です。

全6回は下記から確認できます!




この記事が気に入ったらサポートをしてみませんか?