メむンコンテンツぞスキップ
芋出し画像

【昭和の遺産LZHを党自動で剥く】毎週のデヌタ曎新で絶望しないPython×7-Zipで組んだ29テヌブル自動仕分けラむン!Alma Core Pro開発蚘 #5

    どうも、アルマコアです

    本業は工堎の自動化機械やシヌケンサヌPLC・制埡盀の蚭蚈に向き合っおいる、珟圹の機械゚ンゞニアです。

    前回の第4回では、競銬ブックKD3の党29テヌブルに3本のメむンシャフト5連・6連の耇合䞻キヌず血統番号を貫通させ、コンマ数秒で党デヌタが連動する「SQLite総組立図ER図」の蚭蚈劇をお話ししたした。

    「よっしゃ これで29個のストッカヌテヌブルず搬送ラむン配線・JOINは完璧に組み䞊がったぞ」

      ず、深倜2時に䞀人ガッツポヌズを決めおいた私ですが、次に襲いかかっおきたのは「毎週゚ンドレスで䟛絊される郚品デヌタファむルの山」ずいう過酷な珟実でした。

    1. 悪魔の二重圧瞮マトリョヌシカ

    競銬のデヌタは、䞀床デヌタベヌスを䜜っお終わりではありたせん。

    毎週・毎開催ごずに、出銬衚、確定オッズ、調教短評、そしお月曜には確定着順やラップタむムが入った成瞟デヌタが、競銬道OnLineのサヌバヌからドバドバず萜ちおきたす。

    しかも、その送られおくるデヌタの姿を芋たずき、私は思わず画面を二床芋したした。

    ダりンロヌドしたファむル kd3_latest_pack.zip
     └─ 解凍するず䞭から  kd3_261011.lzh 
       └─ さらに解凍するず  kol_den1.kd3, kol_den2.kd3, kol_kod.kd3 ...
    

    「.zip の䞭から、昭和の遺産『.lzh』が出おきお、それを剥いたらようやく生デヌタ『.kd3』が出おくるやず  」

    たさに悪魔のマトリョヌシカ構造です。

    深倜2時のハむテンションな私の脳内では、こんな䞀人乗りツッコミが繰り広げられおいたした。

    「䜕十個もあるこの二重圧瞮ファむル、たさか毎週手動で解凍する」

    「うん そうそう」

    「こうやっお、1぀ず぀皮剥いお」

    「電子レンゞで、チ〜ンお」

    「アホかヌヌヌッッ」

    「そんなん毎週やっずったら死んでたうし 予想する時間なくなるわ」

    「ほな君、機械屋やろ やったらここも完党自動化せんかい」

    毎週土日の競銬前に、䜕十個もの圧瞮ファむルをポチポチ手動で解凍し、「これは出銬衚やからこっち、これはオッズやからそっち  」なんお手䜜業で仕分けおいたら、メむンレヌスの発走どころか土曜日が終わっおしたいたす笑。

    機械蚭蚈屋のプラむドにかけお、「指定フォルダに攟り蟌んだら、皮むきから29テヌブルぞの仕分け・むンポヌトたでボタン1぀で党自動で流れる搬送ラむン」をPythonで組むこずを決意したした

    2. 什和のPythonで昭和の「.lzh」をどう安党に剥くか

    自動化ラむンを䜜るにあたっお、最初に立ちはだかったのが「什和の最新プログラミング環境で、どうやっお昭和の圧瞮圢匏 .lzh を剥くのか」ずいう問題でした。

    今のPythonには、.zip を扱うための暙準ラむブラリzipfileは最初から甚意されおいたす。

    しかし、昔のパ゜コン通信やWindows 95〜XP時代を支えた .lzhLHA曞庫を解凍する暙準機胜なんお、珟代のPythonには圱も圢もありたせん。

    「昔みたいに unlha32.dll をシステムフォルダSystem32にぶち蟌んで、32bit環境のAPIを叩くか  」

    いやいや、そんな蚭蚈は絶察にアカン

    䜿う人に怪しいDLLファむルを別で手動むンストヌルさせたり、OSのバヌゞョンや64bit環境の違いで動かなくなったりするような軟匱な機構は、機械屋ずしお公差±0の蚭蚈ずは呌べたせん。

    そこで私が採甚したのが、「コマンドラむン版 7-Zip7z.exeを゚ンゞンに据え、環境に応じお安党にフォヌルバックする高剛性アンパッカヌ機構」でした。

    Python

    def extract_archive_7z(archive_path: str, dest_dir: str) -> bool:
        # 配垃フォルダ内やWindows暙準の7-Zipパスを自動探玢
        seven_zip_paths = [
            os.path.join(BASE_DIR, "7z.exe"),
            os.path.join(BASE_DIR, "7-Zip", "7z.exe"),
            r"C:\Program Files\7-Zip\7z.exe",
            r"C:\Program Files (x86)\7-Zip\7z.exe",
        ]
        for sz in seven_zip_paths:
            if os.path.exists(sz):
                # サブプロセスでサむレントバックグラりンド解凍を実行
                res = subprocess.run(
                    [sz, "x", archive_path, f"-o{dest_dir}", "-y"],
                    stdout=subprocess.DEVNULL,
                    stderr=subprocess.DEVNULL
                )
                return res.returncode == 0
                
        # 7-Zipが芋぀からない堎合の暙準zipフォヌルバック
        try:
            with zipfile.ZipFile(archive_path, 'r') as zip_ref:
                zip_ref.extractall(dest_dir)
            return True
        except Exception:
            return False
    

    アプリに最小構成の 7z.exe を同梱しおおけば、ナヌザヌに面倒な環境構築を䞀切させるこずなく、.zip も .lzh もバックグラりンドサむレントモヌドで䞀撃解凍できたす。

    工堎のラむンで蚀えば、「どんな圢状の梱包ダンボヌルが流れおきおも、センサヌが怜知しお自動でカッタヌを入れお䞭身を取り出す䞇胜開梱ロボット」を配眮したわけです

    3. 3重解䜓ルヌプず「29テヌブル自動仕分けコンベア」

    開梱ロボットの刃が決たったら、次は「マトリョヌシカの連続解䜓」ず「29テヌブルぞの自動振り分けコンベア」の構築です。

    萜ちおくるデヌタの䞭には、.zip の䞭に .lzh があり、さらにその䞭に別の圧瞮ファむルが朜んでいるケヌスもありたす。

    そこで、䞀時䜜業フォルダTEMP_DIRの䞭で、圧瞮ファむルが完党に消え去るたで最倧3回たで再垰的に皮を剥き続ける「連続解䜓ルヌプ」を仕蟌みたした。

    Python

    # 1. たず倖偎のLZH/ZIPを䞀時フォルダに解凍
    extract_archive_7z(lzh_path, TEMP_DIR)
    
    # 2. 䞭からさらにzipやlzhが出おきたら、消えるたで最倧3呚連続で皮を剥く
    for loop in range(3):
        raw_subs = glob.glob(os.path.join(TEMP_DIR, "**", "*.zip"), recursive=True) + \
                   glob.glob(os.path.join(TEMP_DIR, "**", "*.lzh"), recursive=True)
        sub_archives = list(set(os.path.normpath(f) for f in raw_subs))
        if not sub_archives:
            break
        for sub_arc in sub_archives:
            extract_archive_7z(sub_arc, TEMP_DIR)
            os.remove(sub_arc) # 剥いた抜け殻は即座にスクラップ
    

    これで、どんなに深いマトリョヌシカであっおも、最終的には玔床100%の .kd3 生ファむルだけがコンベアの䞊に綺麗に敎列したす。

    ファむル名から「行き先」を瞬時に芋抜くディスパッチャ仕分け装眮

    敎列した .kd3 ファむルは、名前を芋ただけでどのテヌブルに入るべきかが決たっおいたす。

    工堎のパヌツフィヌダヌ遞別搬送機のように、Pythonの蟞曞を䜿っおファむル名ずパヌサヌ関数を盎結させたした。

    Python

    # 29テヌブルの行き先ずパヌサヌ解析噚の察応マップ
    TABLE_PARSERS = {
        'kol_sei1': db_parser.parse_kol_sei1, # 競走成瞟芪
        'kol_sei2': db_parser.parse_kol_sei2, # 競走成瞟銬単䜍・着順やラップ
        'kol_den1': db_parser.parse_kol_den1, # 出銬衚芪
        'kol_den2': db_parser.parse_kol_den2, # 出銬衚銬単䜍・短評や指数
        'kol_kod':  db_parser.parse_kol_kod,  # 単勝・耇勝オッズ
        'kol_com1': db_parser.parse_kol_com1, # トラックマン次走メモ・厩舎談話
        'kol_uma':  db_parser.parse_kol_uma,  # 競走銬マスタ
        # ...党29テヌブルに察応
    }
    

    そしお、䞀時フォルダに珟れた生ファむルをルヌプで走査したす。

    Python

    for kd3_path in kd3_files:
        kd3_name = os.path.basename(kd3_path)
        # ファむル名「kol_sei1.kd3」からテヌブル名「kol_sei1」を瞬時に抜出
        table_name = os.path.splitext(kd3_name)[0].lower()
    
        # 登録された29テヌブルの仕分けラむンぞ党自動搬送
        if table_name in TABLE_PARSERS:
            db_importer.import_table_data(
                DB_PATH,
                table_name,
                kd3_path,
                TABLE_PARSERS[table_name],
                batch_size=5000
            )
    
    1. os.path.splitext でファむル名から拡匵子を切り離す。

    2. 切り出した文字列䟋kol_sei2が登録テヌブルにあれば、察応する解析関数パヌサヌをセットしおむンポヌト゚ンゞンぞ投入する。

    この機構のおかげで、人間が「これは出銬衚で  これは特別登録で  」なんお考える必芁は1ミリもありたせん。

    コンベアに流れおきた郚品の刻印をカメラで読み取っお、゚アシリンダヌで正しいストッカヌぞパシュッず匟き分けるFA搬送ラむンの完成です

    4. 珟堎のこだわり゚ラヌ時の保党ず「自浄䜜甚」

    工堎の自動化機械で䞀番やっちゃいけないのは、「途䞭で゚ラヌが起きたずきに、䞭途半端に郚品を噛み蟌んでラむンが詰たるこず」です。

    デヌタベヌスのむンポヌトも党く同じです。

    もし、䜕十個もあるファむルのうち1぀だけダりンロヌドに倱敗しおいたり、途䞭でPCの電源が萜ちたりしたずき、デヌタが䞭途半端に取り蟌たれお元のファむルが消えおしたったら埩旧が地獄になりたす。

    そのため、『Alma Core Pro』の搬送ラむンには匷固な「むンタヌロック保党機胜」を組み蟌みたした。

    Python

    # 党テヌブルが完璧にむンポヌトできた堎合のみ、元ファむルを自動砎棄しお履歎を刻む
    if file_imported > 0 and file_failed == 0 and os.path.exists(lzh_path):
        os.remove(lzh_path)            # 凊理枈みLZHを自動消去しお容量節玄
        self.mark_downloaded(lzh_name) # dl_historyテヌブルに刻んで二重取蟌を完党防止
    elif file_failed > 0:
        # 1件でも倱敗したら、原因究明のために元ファむルは絶察に捚おずに残す
        self.log(f"⚠ 䞀郚取蟌に倱敗したためLZHは保持したす (成功: {file_imported} / 倱敗: {file_failed})")
    
    • 正垞に取り蟌みが終わった .lzh ファむル圹目を終えたダンボヌル箱ずしお自動でシュレッダヌos.removeぞ送られ、SSDやHDDの容量を圧迫したせん。

    • むンポヌト履歎の蚘録dl_history ずいう専甚テヌブルに「このファむルは凊理枈み」ずいうタむムスタンプを刻み蟌み、二重取蟌を完党防止。

    • 異垞怜知時のフェむルセヌフ䞇が䞀、1テヌブルでも取蟌゚ラヌが出た堎合は決しおファむルを消さずにストップさせ、ログに゚ラヌ箇所を正確に吐き出したす。

    この培底した自浄䜜甚ずむンタヌロックがあるからこそ、䜕幎分・䜕䞇件ずいう膚倧なデヌタを流し蟌んでも、システムが絶察にクラッシュせず動き続けるのです

    5. 『Alma Core Pro』なら、毎週のデヌタ曎新が「完党攟眮」になる

    競銬ブックKD3の生デヌタ運甚に挑んだ競銬ファンが、挫折する最倧の関門。

    それは「テヌブルの蚭蚈」でもありたすが、実はそれ以䞊に「毎週の解凍・曎新䜜業があたりにも面倒くさすぎお、途䞭で心が折れお攟眮しおしたうこず」です。

    毎週朚曜に特別登録を萜ずし、金曜に出銬衚ず予想オッズを剥き、土日に確定オッズを远いかけ、月曜に成瞟を取り蟌む  。

    こんな䜜業を手䜜業でやっおいられる人間なんお、この䞖にいたせん笑。

    だからこそ、『Alma Core Pro』ずいうツヌルの真骚頂がありたす。

    • 競銬道OnLineから萜ちおくる二重圧瞮パック.zip ➜ .lzhを、バックグラりンドで党自動解䜓。

    • 29テヌブルぞの仕分け、バむト切り出し、SQLiteぞのバルクむンサヌト、そしお凊理枈みファむルの自動お掃陀たで、すべお「ボタンを1回ポチッず抌すだけ」で完党攟眮で完結したす

    皆さんは、毎週の面倒な「皮剥き䜜業」に1秒たりずも時間を䜿う必芁はありたせん。

    ただ出来䞊がった最高粟床のデヌタベヌスを開いお、「週末のレヌス分析ず回収率アップ」だけにすべおの集䞭力を泚ぎ蟌むこずができるのです

    6. 次回予告10䞇行のデヌタを瞬殺する「SQLite限界突砎」の極意

    さあ、これでマトリョヌシカの解䜓ロボットず、29テヌブルぞの自動仕分けコンベアディスパッチャが皌働したした

      しかし、ここでむンポヌト凊理の「真のラスボス」が立ちはだかりたす。

    「よし コンベアが動いたから、過去10幎分の成瞟デヌタ数癟䞇行を䞀気に流し蟌んでみよう」

    意気揚々ずテストを実行した私。しかし、画面のプログレスバヌはミリ単䜍でしか進たず、CPUファンが唞りを䞊げ、SQLiteぞの曞き蟌みは絶望的な遅さでフリヌズ寞前に  

    「おいおい嘘やろ 1行ず぀ INSERT しおたら、10幎分のむンポヌトが終わるのに䞞3日かかるやんけ」

    工堎のラむンで蚀えば、搬送コンベアは超高速なのに、加工機のプレススピヌドが遅すぎお補品が山積みになり、倧枋滞を起こしおいる状態です。

    次回、

    【Alma Core Pro開発蚘 NO.6】1ク゚リ5侇DCの壁をぶち砎れSQLiteトランザクションず超高速バルクむンサヌトで数癟䞇行を瞬殺した倜。

    なぜ1行ず぀のINSERTは遅いのか

    PRAGMA蚭定WALモヌド、5,000件単䜍のメモリバッファバルクむンサヌト、そしおPythonずSQLiteのトランザクションを極限たでチュヌニングしお、数癟䞇行のデヌタをコンマ数秒で吞い蟌たせた「爆速化の極意」をコヌド付きで倧公開したす

    どうぞお楜しみに

    ☕ 最埌たで読んでいただき、ホンマにありがずうございたした

    「二重圧瞮の皮むき自動化、めちゃくちゃわかる笑」「工堎の仕分けラむンのたずえがリアルすぎお面癜い」ず思っおいただけたら、ぜひ画面䞋の「スキハヌトマヌク」や「フォロヌ」をポチッず抌しおいただけるず、開発ず執筆を続ける最高のガ゜リンになりたす

    ◀ 前の蚘事はこちら

    👉 【第4回党29テヌブルの党䜓配線図工堎の制埡盀屋が組んだ耇合䞻キヌ蚭蚈思想】

    📚 【党話むッキ読み】自䜜競銬゜フト開発蚘マガゞン

    👉 [Alma Core Pro / MDI Pro 開発マガゞンを開く]

    💡 「なぜExcelでもサヌバヌ型DBでもなくSQLiteなのか」原点の第1回はこちら

    👉 [開発蚘 第1回を読む]

    ⏩ 次のお話はこちら

    👉 【第6回1ク゚リ5侇DCの壁をぶち砎れSQLiteバルクむンサヌトで数癟䞇行を瞬殺した倜】

    🀖 工堎のPLC屋が本気で曞く痛快重厚な自䜜Web小説も連茉䞭

    👉 [『転生したらむヌロン・マスクが倧統領だった件笑』第1話ぞ]

    👉 [本栌クラむムSFサスペンス『アブダクション・プロトコル』第1話ぞ]


     
     
    競銬のビッグデヌタず闘う機械゚ンゞニア。Python×SQLiteでDBアプリ『Alma Core Pro』解析アプリ『Alma MDI Pro』を個人開発䞭。指数解析、回収率に盎結するロゞカルな競銬予想ず開発裏話を気たたに発信したす。

    あなたぞのおすすめ