【Python】自動でダウンロードしたcsvを既存のexcelに自動転記させてみる

カテゴリ:Python 投稿:2022年6月17日0:01、更新:2022年6月27日1:26

・記事の概要 

以下の記事でブラウザ操作を自動化し条件指定の上でファイル(csv)をダウンロードまでしたので、そのファイル内容を既存のExcelに自動転記させてみます。

前回と今回の内容を繋げれば特定のURLにアクセスし、抽出条件を設定した上でファイルをダウンロードし、そのファイルをexcel転記するまでが自動化できます。

特定サイトで条件指定してファイルをダウンロードするような処理を自動化してみる


・この記事でできるようになること 

ダウンロードしてきたcsvを特定し、その内容をexcelの指定シート指定セルに転記できるようになります。

もしも業務の定常作業でどこかからファイルを取得して、まとめ用のexcelに転記するようなことがあれば自動化できます。(今回はcsv⇨excelの転記を記載しますが、excel⇨excelの転機の方が容易なので、あえてcsvでの例を書きます。


・前準備 

事前にインストールしておきます。

pip install pandas

pip install openpyxl


・実際のコード 

コメント記載内容で流れはわかるかもしれませんが、いくつか補足もしていきます。

from glob import glob

import os

import shutil

import openpyxl

import pandas as pd


#同DIR内にあるexcelの集計先シートに追記する

wb = openpyxl.load_workbook("まとめ.xlsx")

ws = wb["集計先"]


#globで任意のpathのcsvファイルをリストで取得

files = glob("/Users/user_name/Downloads/*csv")

#取得順に並び替え(sorted_files[-1]が最新)

sorted_files = sorted(files, key=os.path.getatime)


#ヘッダーが複数行かつややこしいので以下のように明示的な指定をする(csvから年月日と平均気温だけ取りたい)

#「header=0」でhederは推測しないでねと指定し、namesでheader指定して、usecolsでどの列を使うかを指定

df = pd.read_csv(sorted_files[-1],encoding='shift_jis',header=0, names=['col0', 'col1', 'col2', 'col3'], usecols=[0, 1])


#B2セルを起点にしてcsv内容を対象excelのシートに記載していく

rows = dataframe_to_rows(df,index=None,header=None)

row_start_idx = 2

col_start_idx = 2

#ループで転記

for row_no, row in enumerate(rows, row_start_idx):

    for col_no, value in enumerate(row, col_start_idx):

        ws.cell(row=row_no, column=col_no, value=value) 


wb.save("まとめ.xlsx")

・ダウンロードしたcsvファイルの指定方法

手前でseleniumでファイルダウンロードをして、このプログラムを実行している想定のため、指定ディレクトリの最新ファイルを対象に取るようにしています。

files = glob("/Users/user_name/Downloads/*csv")」でディレクトリ内のcsv拡張子ファイルをリスト取得し、

sorted_files = sorted(files, key=os.path.getatime)」で取得日時でソートをかけています。


・csvの読み込み

pandasの「read_csv」で読み込んでいますが、引数の内容が一見複雑になっています。

これは実際に前記事のcsvを見てみてもらうとわかるのですが、csvのヘッダが複数行かつヘッダ自体が少々おかしなことになっている状態であるため、①既存のヘッダを無視して②こっちでヘッダ名を決めて③ヘッダを直接指定する、ようなことをしています。正常かつ1行ヘッダのcsvの場合「pd.read_csv(sorted_files[-1],encoding='shift_jis')」で問題ないかと思います。


ループで転記の部分

少し複雑にも見えるかもですが、csvで指定した内容分をexcelの指定箇所からループ転機させているだけです。

excelにそのまま貼り付けるだけであればappendなどで容易にできます。


・全体のコード 

ブラウザ自動操作と繋げて一個にするとこんな感じですかね。(長い上に見にくい。。。申し訳ないです。)

from selenium import webdriver

from webdriver_manager.chrome import ChromeDriverManager

from selenium.webdriver.common.by import By

from selenium.webdriver.support.ui import WebDriverWait


from glob import glob

import os

import shutil

import openpyxl

import pandas as pd


###ブラウザ自動処理開始###

#ブラウザの立ち上げ

driver = webdriver.Chrome(ChromeDriverManager().install())

#実際のURL指定

driver.get("https://www.data.jma.go.jp/gmd/risk/obsdl/index.php")


#csv出力の条件指定

##フロント側での要素描画の時間を待機,場所は東京都を選択

prefectures = WebDriverWait(driver, 5).until(lambda x: x.find_element(By.ID, "pr44"))

prefectures.click()

##地域も東京を選択

area = WebDriverWait(driver, 5).until(lambda x: x.find_element(By.XPATH, "/html/body/div[1]/div[2]/div[1]/div[2]/div[1]/div/div[2]/div[1]/div[2]/div[1]/div[2]/div[9]/div"))

area.click()


#項目の選択

##項目を選ぶへ

element_select = driver.find_element(By.ID, "elementButton")

element_select.click()

##日別値を選び

elemen_category = driver.find_element(By.XPATH, "/html/body/div[1]/div[2]/div[1]/div[2]/div[1]/div/div[2]/div[1]/div[2]/div[2]/div[2]/div[1]/div/div[1]/div[2]/label/span")

driver.execute_script("arguments[0].click();", elemen_category)

#日平均気温を選ぶ

elemen_item =  driver.find_element(By.XPATH,"/html/body/div[1]/div[2]/div[1]/div[2]/div[1]/div/div[2]/div[1]/div[2]/div[2]/div[3]/div[1]/div[1]/table/tbody/tr[1]/td[1]/span/label/span")

driver.execute_script("arguments[0].click();", elemen_item)


#期間の選択

##期間を選ぶへ

period_select = driver.find_element(By.ID, "periodButton")

period_select.click()

#直近1ヶ月(連続した期間)

period_category = driver.find_element(By.XPATH, "/html/body/div[1]/div[2]/div[1]/div[2]/div[1]/div/div[2]/div[1]/div[2]/div[3]/div/div/div[1]/div[2]/div[1]/input[2]")

driver.execute_script("arguments[0].click();", period_category)


#csvDLボタン

csv_btn = driver.find_element(By.XPATH, "/html/body/div[1]/div[2]/div[1]/div[2]/div[1]/div/div[2]/div[2]/div/div/div[1]/div[2]/span/img")

csv_btn.click()


driver.close()

###ブラウザ自動処理完了###


###ファイル転記処理開始###

#同DIR内にあるexcelの集計先シートに追記する

wb = openpyxl.load_workbook("まとめ.xlsx")

ws = wb["集計先"]


#globで任意のpathのcsvファイルをリストで取得

files = glob("/Users/user_name/Downloads/*csv")

#取得順に並び替え(sorted_files[-1]が最新)

sorted_files = sorted(files, key=os.path.getatime)


#ヘッダーが複数行かつややこしいので以下のように明示的な指定をする(csvから年月日と平均気温だけ取りたい)

#「header=0」でhederは推測しないでねと指定し、namesでheader指定して、usecolsでどの列を使うかを指定

df = pd.read_csv(sorted_files[-1],encoding='shift_jis',header=0, names=['col0', 'col1', 'col2', 'col3'], usecols=[0, 1])


#B2を起点にしてcsv内容を対象excelのシートに記載していく

rows = dataframe_to_rows(df,index=None,header=None)

row_start_idx = 2

col_start_idx = 2

#ループで転記

for row_no, row in enumerate(rows, row_start_idx):

    for col_no, value in enumerate(row, col_start_idx):

        ws.cell(row=row_no, column=col_no, value=value) 


wb.save("まとめ.xlsx")

###ファイル転記処理完了###

print("処理完了")


・まとめ 

いかがだったでしょうか。

最後のコードは長すぎますので分離してもいいのですが、個人的にはブラウザ操作の部分は拡張機能のseleniumを使い、そこでできた.sideファイルを読み込ませて処理できるといいかなあと思ったので、そういったことも記事にできればと思います。


コメント一覧

コメント投稿ページへ


書いている人

のぎ
PG->SE->PMとして働き、現在はIT企業で新卒採用の担当をしています。長期育休取得明けで0歳娘の対応に毎日バタバタです。笑
採用業務をしつつ社内利用ツールなど作成しており、当ブログも勉強の一環でコーディングして作成しています。 エンジニア領域、人事・採用領域、育児関連など発信していきます。