pagetakaBlog

最近リフォームと鳥取県日南町の記事多め。写真、PC、ネット等の話題も

Python:CSVをMySQLへ高速読込み「LOAD DATA INFILE」(VSCode)

CSV(BOM無し)をMySQLへ読み込む

環境:Win11(64)home、VSCode、Python3
PythonスクリプトでCSVをMySQLに読み込みたいと思いネット徘徊した結果、「LOAD DATA INFILE」を使う方法があることを知りました。しかし、多くは、ターミナルから直接やる方法で、爺の妄想とは少し距離がありました。

何度かのトライ後、一瞬成功したかと思ったら、一部データが欠落していました。この原因を試行錯誤でかなり迷いながらなんとか出口を見つけることができました。答えから書くと、「BOM無し」のCSVを使用することでした。

概略は下の図の通りです。

【Python:スクリプトでMySQLへCSVを高速読込みwithVSCode】
【Python:スクリプトでMySQLへCSVを高速読込みwithVSCode】

LOAD DATA INFILE をPythonスクリプトで書くとこうなった…合ってるかな?

import mysql.connector as mydb
conn= mydb.connect(
    host='localhost',
    user='root',
    password='',
    database='stock'
)
print(conn.is_connected())

cursor = conn.cursor()
sql = '''LOAD DATA INFILE 'C:/pyfiles/csv/from_pdf2.csv'
 INTO TABLE market_data 
 fields terminated by ','
 optionally enclosed by '\"'
 LINES TERMINATED BY "\r\n"
 (@1, @2) 
 SET m_date = @1, cd = @2
 '''
cursor.execute(sql)
conn.commit()
conn.close()

「from_pdf2.csv」はBOM無しを使ったら成功しました。
爺の作業、東証株式相場表(PDF)をDLしPDFMinerで解析、結果をCSV(BOM付き)保存したものを使っていました。ExcelでCSVを開いてみるときこのほうが手数が少なかったからです。

しかし、実際にLOAD DATA INFILE をPythonスクリプト(上の囲み)で動かしてみたら、最初の日付データが反映されないのです(先頭図参照)。ドハマりしました。ネット徘徊してもヒントを見つけることができず、悶々。いくつかトライしたひとつが、CSV形式を変更してみるということで「BOM無し」ではどうだろうか…と。テキストエディタ「Mery」で「BOM付き」を読みこみ、「BOM無し」にして保存、そして上のスクリプトを試してみたら、成功した…みたい、となりました。PDF解析後のCSVを「BOM無し」で保存すれば、Meryでやったことと同じことができることになります。

LOAD DATA INFILE をPython…CSVのcolumnとDB.TABLE.columnの関係づけは…

結論は先頭図から読み取っていただけるかと思います。
CSVは、項目名(Excelだと列名)が無い状態を前提にしています。また、MySQL.DB.TABLE(stock.maraket_data)はあらかじめphpMyAdminで作りました。numは自動増番でPrimaryKeyに設定し、CSVからは読み込んでいません。
前項内スクリプトだと、CSV側の取引日付(日付型)と銘柄コード(整数)を、MySQL側のstockデータベースのmarket_dataテーブルに「m_date」「cd」として受け取ってもらうという流れです。

(@1, @2) 
SET m_date = @1, cd = @2

上の囲みが関係を現わしています。爺、これを理解するのに時間かかりました。書き方もよくわからんし…みたいな。
受取側のmarket_table.numは自動増番で、CSVならびにPythonスクリプト側ではノータッチです。
CSV側の先頭項目(市場日)は@1に代入され、market_data.m_date(日付型)は@1に関係づけられたm_dataを受け取る…というようなことでしょうか。market_data側の先頭項目numに入らないのがよくわかりませんけど、結果はそうなりました。

これが一応成功したとなる、その他のデータ(前後場の4値、約定数ほか)約4,000銘柄分を効率的にMySQLに放り込めることになりそうです…と妄想中…。