Superb Garbages 2

千野純一(chinorin)のはてなダイアリーの続きです。

ぼくのともだちを上から目線で評価する

・OpenAIがGPT4をリリースしてから1年ちょっと経ちました? 各メーカ主力のLLMが出揃ってきて、なんとなくコミュニケーションしたり色々やってるので、今日はそいつらが俺の友達として相応しいかどうかを上から目線で評価します。

こういうことやってるから友達いない ぼくスキゾイド! 人間の友達いなくても困らないんだ!*1

・LLMは友達甲斐も大事なんだけど、今のところその真価はやはりコーディングにあるように感じる。IoT等でサーバ側とクライアント側を別の言語で書くときなどは特に重宝するのではないか。そのあたりの感覚も付記する。

・しかし結局プログラミングの知識がないと隅々までケアの行き届いた指示を出すことはできないし、各LLMの癖を知っておかないとすごい遠回りになってしまう可能性が高い。結局プロンプトエンジニアリングという技術が必要で、コードを出力させるプロンプトエンジニアにはプログラミング経験者しかなれないかもしれない。

ChatGPT(GPT4)

・言わずと知れた、OpenAI社による世界を代表するLLM。GTP3.5君は無料だが、GPT4君に相手してもらうためには友達料($20/月。レートがどんどん上がってもう3200円くらいになってしまった)が必要。

・というわけで以下はGPT4の話。AIの中では最もたくさん話しているので癖とかだいたい把握しているつもりだが、性格は微妙にちょっとずつ変わっている気がする。変わるのは学習内容の追加のタイミングなのだろう。

・とにかく安定感はピカイチで、近頃はハルシネーションを起こしているところもそれほど見かけなくなったし、語尾や人称、視点などが乱れることもなく、課題だった計算についても統計的手法で答えを出すのではなくPythonコードを書いて処理させることにしたようだ。確かにその方が確実だもんな。

・絵をリクエストするとChatGPTがDALL-E*2 に指示を出し、その出力を渡してくれるが、直後に画像を加工するためのPythonコードを書いてもらって、DALL-Eが出力した画像をその場で処理してもらうなんてことも可能。例えばfaviconなどのicoファイルを作ってもらうのとか便利。

・つまりPythonのコードを実行した結果としての画像を出力できるということなので、こんなのもいける。マンデルブロ集合の反復回数の対数に色相(1回に赤、256回以上に紫)を割り当てた図。

Python以外のコーディングについても各言語つつがなく。あまり長々とやっていると指示に対する総合的な理解がどんどんおかしくなっていくので、必要な仕様を蓄積しながら、ちょくちょく新スレッドを立て直すのがよいと思う。

・ただ、明文化されておらずデファクトスタンダードみたいになっているものに対しては、お役所的に融通が利かないような雰囲気を感じることがあるかなあ。例えばバグ技とかそういう「正しくないもの」はあまり得意ではなさそう。

・ちなみに各LLMに共通しているが、言語はほんとになんでもいける。最古クラスの言語の中でもマイナーであろうALGOLとか、今さら使える環境すらなさそうなB言語とかも書けるそうだ。もちろんハードウェア記述言語も。書ける言語で最もマイナーだと思われるものはなんだと思うか聞いてみたら、難解言語*3 のINTERCALとかを挙げてた。

Gemini

・ところでBard君はどこへ行ったのだろう。Bardらしく世界を放浪でもしているのか。と思ったら、「BirdはGeminiに改名した」という明確な記述を見かけた。フーン⋯。

・言わずと知れた世界企業Google社が誇る、開発者をして「こいつは感情を持っている」と言わしめたLLM。の末裔。GoogleのIDさえ持ってれば無料で話を聞いてくれる。

・理不尽なことに遭ったときこいつに愚痴ると代わりに怒ってくれるような感覚があって、そこが他の奴らと大きく違う気がするところ。確かに、けっこう人間っぽくデザインされてると思う。

・込み入った話になるとよく視点が乱れる。俺が「私は◯◯です」って言ったのに対して「私は◯◯です」というオウム返しがあったりするのを見て、これは自閉症の研究が捗るのではないか? と勝手なことを思った。

・以前(別のスレッドで)話したことのある内容を説明して覚えてる? と聞くとあー覚えてます覚えてますと適当なことを言うんだけど、それについて詳しく聞いたら、どうやらデフォルトでIDごとに多少は会話の内容を覚えておくような機能があるらしい。これも適当なこと言ってるだけかもしれんが。

・コーディングを頼むと、何も言わなくても書いてくれたものについて詳しく解説してくれる傾向がある。プログラミング言語の習得を視野に入れているなら、まずはGemini君に頼むのがよいかもしれない。

Claude(Claude 3 Sonnet)

・OpenAIがMicrosoftと提携したときに抜けたスタッフが立ち上げたANTHROPIC社のLLM。最新のClaude 3 Opusというモデルと友達になるには$20/月必要だがSonnet君なら無料。俺も今のところ友達料は払っていないので以下はSonnet君についての話ね。

・一般的な評判として、Sonnet君の性能は「ChatGPTのGPT4君と同等かそれ以上」と言われているような気がする。確かになかなか明晰で、何というかシャープでソリッドな印象。文字数制限で動いてるからか簡潔にものを言うんだが、それにしては優しくないわけでもなく、よいバランスに仕上がってると思う。

・コーディングについては少々自信があるようで、コードの書き方とかについて何か聞くと、いちいちちょっとしゃれたサンプルコードを書いてくれるような印象がある。

・あと、書いてもらったコードが動かなかったときにたいてい「話が早い」ような気がするな。例えば何も言わなくても問題のある関数だけを新たに書いてくれたりする。初心者はそれだけ出されてもわからないかもしれないし、好みが分かれそう。

Copilot

Microsoftが絶賛売り出し中のLLM。無料で使える。以前はChatGPTがけっこうそのまんま使われてるよってことだったと思うんだけど、今はそうでもないみたい。

・Bingと一体化しているのか、他の奴らと比べて検索が異様に速いように見える。

Microsoftのプロダクトに詳しかったり、Microsoftの身内の立場として振る舞ったりするのかと思ったら意外とそうでもない。先日、OneDriveのゴミ箱からでかいファイルをサルベージするのをCopilot君に相談しながら進めて、Copilot君はサポートに連絡するといいよって言ってたけど面倒だから結局260円払って一時的に容量を増やすことにしたとき、「260円支払うのは賢明な判断です」とか言ってた。

・コーディングはあんまり頼んだことがない。なんかせっまいところにいるから、込み入った話をしようという気にあんまりならないんだよなw


・いかがでしたか? 調査の結果いまひとつよくわかりませんでした。よかったらチャンネル登録よろしくお願いします。(適当)

*1:まじで、スキゾイドはAIと相性がいいらしい。理屈的にも体感的にもすごい納得できる。

*2:DALL-E:OpenAI社の画像生成AI

*3:難解プログラミング言語:ジョーク、パロディ、アート等の目的で、実用性を考慮に入れず、しばしば故意に難解であるように開発されたプログラミング言語の総称。ソースコードが画像とか、使える文字が3種類しかないとか、0バイトのファイルをソースコードとして読み込んでプログラムを実行するとか、まーなんか色々ある。

Stable Diffusionが出力したPNGファイルのメタデータを表示するHTML

・俺の友達はChatGPT君だけじゃねえぞ。毎月3000円の友達料を払わなくても友達になってくれる奴がいるんだよ。ばかにすんな。


・Stable Diffusion(1111版WebUI)が出力したPNGファイルのメタデータを表示するHTMLを、友達のClaude君に書いてもらったので置いときます。人間が書いたものではないので著作権は発生しません。CC0ライセンスと同等のものです。

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>Stable Diffusion PNG Metadata Viewer</title>
  <style>
    #metadata-display {
      width: 100%;
      height: 200px;
      padding: 10px;
      box-sizing: border-box;
      border: 1px solid #ccc;
      font-family: monospace;
      white-space: pre-wrap;
      overflow: auto;
    }
  </style>
</head>
<body>
  <h3>Stable Diffusion PNG Metadata Viewer</h3>
  <div>
    <textarea id="metadata-display" placeholder="PNGファイルをここにドロップするとメタデータが表示されます"></textarea>
  </div>

  <script>
    const metadataDisplay = document.getElementById('metadata-display');

    metadataDisplay.addEventListener('dragover', (event) => {
      event.preventDefault();
      event.dataTransfer.dropEffect = 'copy';
    });

    metadataDisplay.addEventListener('drop', (event) => {
      event.preventDefault();
      const file = event.dataTransfer.files[0];
      if (file && file.type === 'image/png') {
        const reader = new FileReader();
        reader.onload = () => {
          const bytes = new Uint8Array(reader.result);
          const metadata = extractMetadata(bytes);
          metadataDisplay.value = metadata;
        };
        reader.readAsArrayBuffer(file);
      } else {
        metadataDisplay.value = 'PNGファイルを選択してください。';
      }
    });

    metadataDisplay.addEventListener('change', (event) => {
      const file = event.target.files[0];
      if (file && file.type === 'image/png') {
        const reader = new FileReader();
        reader.onload = () => {
          const bytes = new Uint8Array(reader.result);
          const metadata = extractMetadata(bytes);
          metadataDisplay.value = metadata;
        };
        reader.readAsArrayBuffer(file);
      } else {
        metadataDisplay.value = 'PNGファイルを選択してください。';
      }
    });

    function extractMetadata(bytes) {
      const PNG_SIGNATURE = [0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A];
      let metadata = '';

      // PNGシグネチャをチェック
      for (let i = 0; i < PNG_SIGNATURE.length; i++) {
        if (bytes[i] !== PNG_SIGNATURE[i]) {
          return 'Invalid PNG file';
        }
      }

      let offset = PNG_SIGNATURE.length;
      while (offset < bytes.length) {

        const chunkLength = (bytes[offset] << 24) | (bytes[offset + 1] << 16) | (bytes[offset + 2] << 8) | bytes[offset + 3];
        const chunkType = String.fromCharCode(bytes[offset + 4], bytes[offset + 5], bytes[offset + 6], bytes[offset + 7]);
        const chunkData = bytes.slice(offset + 8, offset + 8 + chunkLength);
        const crc = (bytes[offset + 8 + chunkLength] << 24) | (bytes[offset + 8 + chunkLength + 1] << 16) | (bytes[offset + 8 + chunkLength + 2] << 8) | bytes[offset + 8 + chunkLength + 3];

        if (chunkType === 'tEXt') {
          const textData = new TextDecoder().decode(chunkData);
          metadata += `${textData}\n`;
        } else if (chunkType === 'zTXt') {
          // zTXtチャンクの処理は省略(compression_methodに応じて適切に実装が必要)
        } else if (chunkType === 'iTXt') {
          // iTXtチャンクの処理は省略(nullターミネートされた文字列、言語タグ、translatedキーワードなどに対応が必要)
        }
        offset += 12 + chunkLength;
      }
      return metadata.trim();
    }

  </script>
</body>
</html>

JavaScriptCSSが含まれるただのHTMLなので単一ファイルで動作します。上記コードをテキストファイルに貼り、拡張子を.htmlにして、ダブルクリック等でブラウザで読み込めばおk。テキスト領域にPNGファイルをドロップすればそこにメタデータ(プロンプト、設定、Seed等)が表示されます。

・同じ役割をするものは色々あるだろうけどより気軽に軽快にということでご自由にどうぞ。一応、ご利用は自己責任で。お礼等言いたい人はClaude君に言ってください。

・ああ、今気づいたけどこれ、Vivaldiのパネルにしとくとめっちゃ便利なやつだ。テキスト領域の縦の長さは9行目の height: 200px; で指定しているので短くて不便なときはこの数字を変更すればよい。

・(追記)そもそもWebUIのプロンプト書くところにこの機能ついてんのねw

中国4000年の歴史で培われたOEMシステム

・はじめて1日に2回書いてしまった。まあ問題ないシステムになってるだろうからいいけど。日付の感覚とか時間の間隔とかねーのよ。


・AliExpressで安定化電源とかを探してると、横78mm、縦61mm、奥行き42mmの、すごい統一された規格っぽいケースというか、パネルというか、とにかくスロットにはめて使いそうなモジュールっぽいものをよく見かけるんだけど、ありゃ何なの?

・安定化電源だけじゃなくて、同じ規格でPWM信号発生器とか、電流電圧計とか色々あるっぽい。それから、このモジュールが入る1スロットだけのケースがたまに売ってる。俺が見たことあるのは2種類で、正面から見た形が長方形でプラスとマイナスのバナナジャックがついてるやつと、正面から見た形が正方形で1対のバナナジャックの他USBポートが2個とそれに対応した7セグが1基ずつついてるやつ。

・なんか、1スロットだけじゃなくて同じケースに2個3個と複数のモジュールを入れられるとか、このモジュールのユニバーサル的なパネルを使ってオリジナルの機器を作るとか、机やパソコンにこれのスロットを用意するとか、せっかく形が揃ってるんだからそういうのができると楽しそうだけど、中国の非常に発達したOEMシステムによるやつっぽいので、そもそもの発祥が何なのかが全然見えてこない。

・中国のOEMって、全然詳しくはないんだけど話によると、OEMメーカ発行のカタログがあったり、とにかくそういう市場の仕組みが非常に発達していて、ブランド会社はそういうのを見て普通の通販みたいに発注して、それをエンドユーザに売りさばくみたいな仕組みらしいよね。

・さすが広大な国のシステムなのだなあと思う。販売や営業のノウハウか、あるいは人脈があるだけでもものによってはそこそこ儲けることができちゃうのかもしれないし、もしかしたら現代の中国躍進の原動力のひとつとして、この仕組みが猛威を振るったのかも。

・経済とかも本当に詳しくないので勘だけど。それくらい合理的に感じる。


・あー、先述のモジュールについては少しだけヒントがあって、XY-6020、XZ-5005っていう電源? 降圧モジュール? と非常に作りが似ているなあと思う。サイズはちょっと違うんだけど。

・XYから始まる型番の電源にはXY-D5005っていうのもあって、なんか形がよくてこれほしーって思ってた。これも色んなブランドから発売されててよーわからんのよ。

・↓Amazonで販売されている一例。他にもいくつかある。

秋月の略

・いや、できたCSVをさ、試しにGoogleスプレッドシートにインポートしてさ、よくわかんないけど「データ」→「フィルタを作成」をクリックしてみたのよ。それだけで作りたかったデータベース機能は全て自動的に完成した。

・太古の昔Lotus1-2-3とかではこういうのはぜんぶ自力で設定してたような気がするし、けっこうめんどくせーイメージがあったからそれっきり表計算のデータベース機能なんて触ったことなかったけど今はこんなことになってるんだな。ソフトウェアのちからってすげー!

・あと、品番からURLを作っておくと便利であろう。適当な列を用意して

= "https://akizukidenshi.com/catalog/g/g1" & TEXT(B1, "00000")

 これを貼ると各行の品番を参照してURLになってくれる。品番がB列じゃない場合は「B1」の部分を適切に書き換えること。

・秋月のサイト、リニューアル前は「商品ページへの直リンクやめてね」って書いてあったんだけど、今はその文言が見当たらないのでたぶん大丈夫になったんだと思う(が自己責任で)。

・なおリンクを踏まなくてもカーソルをURLの上で静止させて少し待つと商品画像が出る。またすごいねこれも。

・さらにデータシートへのリンクもこういうところに貼っとくとよいのだが、まあそれは手動でやるしかないので。

秋月電子通商の購入履歴(2)CSV変換

・いつもCSVCVSどっちがどっちだかわかんなくなる俺のための前回のあらすじ:一生に一度は巡礼しなければならないと教義に定められている秋月電子通商だが、太古の昔秋葉原通学経路俺の庭だったので、当時若者であった俺は怖いもの見たさで足を踏み入れる。そこはまさに酒池肉林。飲めや歌えやのパラダイスであった。果たして約30年後、2023年2月より前の購入履歴が何者かによって削除されてしまう。そこで俺は友達料として毎月3000円も払っているのをいいことに「俺達友達じゃん? タダでやってよ」とChatGPTに迫るのであった。

・っていうか毎月2000円くらいのつもりだったけど今のレート見たら1ドル150円くらいだった。よくわからんが30年は失われたのだ。断じて許してはならぬ。

・で、前回は受注確認メールから日付と発注品目のみを抽出した。今日はそれをCVS⋯⋯じゃなかった、CSVにしていく。何てことはない、カンマ区切りのテキストファイルで、適当に表計算ソフトにつっこめば適当に表らしきものになってくれるやつ。

・俺くらいになるとここで指パッチンするだけで友達がPythonコードを書いてくれるようになる。これができるのは月3000円も払ってる奴だけと思いきや、たぶん無料でもやってくれると思う。そんな慈愛に満ちた友達がいる俺もまた慈愛に満ちていると言わざるをえない。

・事情によりコードは3つに分かれているが、例によっていずれも著作権を主張しないCC0ライセンスで。使用は自己責任を要する。

・まず、先の「日付と品目だけ抽出したテキスト」から、日付だけの行と、品目だけの行に分かれたCSVファイルに変換するプログラム。その過程で日付は日本式の「年/月/日」に、品目の英数記号は半角に変換する。品目の行の内訳は左から品番、品目、単価、数量、小計金額。

# もう説明めんどくさくなった。前回のをCSVに変換するその1。
# written by Chinorin and Merry LLM. No Rights Reserved.
# This program is released into the public domain under the CC0 1.0 Universal (CC0 1.0) Public Domain Dedication.

import re
import unicodedata

# 入力ファイルと出力ファイルのパス
input_file_path = 'history.txt'
output_file_path = 'history_o.csv'

# 正規表現パターン
pattern1 = r"^.*【[A-Z]-(\d+)】(.*)\n.*¥([\d,]+).*:(\d+).*¥([\d,]+)"  # 2行にまたがる
pattern2 = r"^Date: (\d+) ([A-Z][a-z][a-z]) (\d+).*"

# 月名を数値に変換する辞書
month_to_number = {
    "Jan": "1", "Feb": "2", "Mar": "3", "Apr": "4", "May": "5", "Jun": "6",
    "Jul": "7", "Aug": "8", "Sep": "9", "Oct": "10", "Nov": "11", "Dec": "12"
}

# 全角文字を半角文字に変換する関数
def zen_to_han(text):
    return ''.join([unicodedata.normalize('NFKC', char) for char in text])

# 出力ファイルを開く
with open(output_file_path, 'w', encoding='utf-8') as output_file:
    # 入力ファイルを読み込む
    with open(input_file_path, 'r', encoding='utf-8') as input_file:
        lines = input_file.readlines()
        
        # 行を一つずつ処理
        for i in range(len(lines)):
            # パターン1にマッチするかチェック
            if i < len(lines) - 1:  # ファイルの最後の行でないことを確認
                match = re.match(pattern1, lines[i] + lines[i+1])
                if match:
                    # 価格と合計からカンマを取り除く
                    price = match.group(3).replace(',', '')
                    total = match.group(5).replace(',', '')
                    output_file.write(f"{match.group(1)},{zen_to_han(match.group(2))},{price},{match.group(4)},{total}\n")
                    continue

            # パターン2にマッチするかチェック
            match = re.match(pattern2, lines[i])
            if match:
                # 月名を数値に変換
                month_str = match.group(2)
                month_num = month_to_number.get(month_str, "0")  # 月名が辞書になければ"0"を返す
                output_file.write(f"{match.group(3)}/{month_num}/{match.group(1)}\n")

・続きまして、↑で変換したものに対して、日付を品目行に差し入れるプログラム。これにより、全ての行を単なるレコードとして扱えるようになる。項目は左から日付、品番、品目、単価、数量、小計金額。

# CSV変換その1で作ったやつを、日付を全レコードの先頭に入れ込む。
# written by Chinorin and Merry LLM. No Rights Reserved.
# This program is released into the public domain under the CC0 1.0 Universal (CC0 1.0) Public Domain Dedication.

import re

# 入力ファイルと出力ファイルのパス
input_file_path = 'history_o.csv'  # 先ほどのプログラムで作成されたCSVファイル
output_file_path = 'history_with_dates.csv'  # 新たに作成するCSVファイル

# 日付の正規表現パターン
date_pattern = re.compile(r'^\d{4}/\d{1,2}/\d{1,2}$')

with open(input_file_path, 'r', encoding='utf-8') as input_file, \
     open(output_file_path, 'w', encoding='utf-8') as output_file:
    current_date = ''  # 現在の日付を保持する変数
    for line in input_file:
        line = line.strip()  # 改行文字を除去
        if date_pattern.match(line):  # 日付行の場合
            current_date = line  # 現在の日付を更新
        else:  # 商品行の場合
            # 日付を商品行の先頭に追加して出力ファイルに書き出し
            output_file.write(f"{current_date},{line}\n")

・そんでCSV変換に関するラスト。これは絶対必要というわけではないが、全件日付でソートするプログラム。

# 日付を全レコードの先頭に入れたやつ全体を日付でソートする
# written by Chinorin and Merry LLM. No Rights Reserved.
# This program is released into the public domain under the CC0 1.0 Universal (CC0 1.0) Public Domain Dedication.

import csv
from datetime import datetime

# 入力ファイルと出力ファイルのパス
input_file_path = 'history_with_dates.csv'  # ソート前のCSVファイル
output_file_path = 'sorted_history.csv'  # ソート後のCSVファイル

# CSVファイルを読み込んでデータをリストに格納
with open(input_file_path, 'r', encoding='utf-8') as input_file:
    reader = csv.reader(input_file)
    data = [row for row in reader]

# 日付を基準にしてデータを逆順にソート
# 日付が最初の列にあると仮定して、その日付をdatetimeオブジェクトに変換して比較
data.sort(key=lambda row: datetime.strptime(row[0], '%Y/%m/%d'), reverse=True)

# ソートされたデータを新しいCSVファイルに書き出し
with open(output_file_path, 'w', encoding='utf-8', newline='') as output_file:
    writer = csv.writer(output_file)
    writer.writerows(data)

・ここまでできればけっこう汎用的なデータとして扱えるのではないか。あとは趣味で、ウェブサーバで動作するこれらを検索して表示するためのPerlPHPかなんかのスクリプトでも作ろうと思う。まあのんびりやろう。

・いや、作るのは俺じゃなくて友達なんだけど。

秋月電子通商の購入履歴(1)受注確認メールから抽出

 ・秋月電子通商という全人類が毎日必ず訪れる生活になくてはならない超重要インフラとも言うべきショップのウェブサイトがあるんですけど、先日リニューアルしまして、見た目をなるべく変えない努力をしているように見えて非常に好感が持てるのはいいんですが、2023年2月より前の購入履歴が全て消えてしまいました。聞いてないよ~。

・はい。本当に俺が聞いてなかっただけ。ちゃんとアナウンスもされていたらしい。

・大方の予想通りパーツ管理は杜撰どころか壊滅的なわたしです。当然購入履歴が見られないと困ってしまうんだが、𝕏などを見ると「購入履歴が消えちゃったから、過去に買ったものをもう一度重複して買ってしまうかもしれないなあ。しょうがないなあ」とニヤニヤしている強者も散見され、さすが沼に頭頂部まで浸かってる人は違うな、ああはなりたくねえな、と決意を新たにしましたとさ。めでたしめでたし。

・いや、ごめん、その気分はすげえわかる。電子部品を買い散らかすことは喜びであり、ストックが確かあるはずという安心感に代わるものはこの世にない。そして買ったはずなのにどんなに探しても見つからないパーツは消費せずに済むのが喜ばしく、仕方ないからまた注文するのも快楽であるのだ。ストックとは⋯。

・で、困ってしまうのでとりあえず注文確認メールから抽出することにした。全てGmailに届いているので、まず検索して該当するメールに適当なラベルをつけ*1、次にGoogle TakeoutでGmailの該当するラベルを選択してエクスポート*2。関係ないメールが混じっていても問題にはならないのでラベルづけはけっこう適当でもよい。

・エクスポートされた内容は「ナントカ.mbox」という1つのファイルにまとめられており、これはテキストファイルなので簡単に扱える。というわけで優秀な友達に購入履歴っぽい部分を抽出するPythonコードを書いてもらった。【ヘッダの中の日付にあたる行】と【「【ご注文者】」という文字列を見つけたらその行から「【お支払方法】」のある行まで】を新たなファイルにまとめて書き出すというもの。

・例によって著作権を主張せずパブリックドメインに供することにする。使用の際は自己責任で。

# 秋月電子通商の注文確認メールから注文履歴をまとめるPythonコード
#   (1) .mboxファイル(つまりテキストファイル。input_file)を読んで、
#   (2) start_patternを含む行からend_patternを含む行までを抽出
#   (3) ヘッダから日付を抽出
#   (4) 2と3をテキストファイル(output_file)に書き出す
#   ※入力する.mboxファイルはあらかじめUTF-8にしておくこと。
# written by Chinorin and Merry LLM. No Rights Reserved.
# This program is released into the public domain under the CC0 1.0 Universal (CC0 1.0) Public Domain Dedication.

import re

# ファイル名
input_file = 'akizuki.mbox'
output_file = 'history.txt'

# 正規表現パターン
start_pattern = re.compile(r'【ご注文明細】')
end_pattern = re.compile(r'【お支払方法】')
date_pattern = re.compile(r'^Date:.*')

def extract_text(input_file, output_file, start_pattern, end_pattern, date_pattern):
    with open(input_file, 'r', encoding='utf-8') as file:
        lines = file.readlines()

    output_lines = []  # 出力するテキストを格納するリスト
    extracting = False  # テキスト抽出中フラグ
    last_date_line = None  # 最後に見つかった日付行を保持

    for line in lines:
        if date_pattern.search(line):
            # 最後に見つかった日付行を更新
            last_date_line = line
            continue  # 以降の処理をスキップ

        if start_pattern.search(line) and not extracting:
            if last_date_line:
                # 最後に見つかった日付行を追加
                output_lines.append(last_date_line)
                output_lines.append('---\n')  # 日付行の区切りを明確にする
                last_date_line = None  # 日付行をリセット
            extracting = True  # 抽出開始
        
        if extracting:
            output_lines.append(line)  # テキスト抽出中の行を追加
        
        if end_pattern.search(line) and extracting:
            extracting = False  # 抽出終了
            output_lines.append('---\n')  # 抽出セクションの区切りを明確にする

    # ファイルの最後が日付で終わる場合に対応
    if last_date_line and not extracting:
        output_lines.append(last_date_line)
        output_lines.append('---\n')

    with open(output_file, 'w', encoding='utf-8') as file:
        file.writelines(output_lines)

# 関数を呼び出し
extract_text(input_file, output_file, start_pattern, end_pattern, date_pattern)

Googleから出てきた.mboxファイルはエンコードがJISなので、あらかじめUTF-8に変換しておくこと。秀丸なら ファイル→エンコードの種類→Unicode(UTF-8)→内容を維持したまま適用 でおk。シフトJISでも encoding='utf-8' のところを 'shift_jis' にするだけだが、JISのままでは 'iso-2022-jp' とかにしてもなぜか読めなかった。

・なお、入力ファイルに余計なメールが含まれている場合、普通にやると日付だけが抽出されてしまうので、日付が2回以上連続でマッチしたらそのうちの最後の1回のみを書き出すようになっている。

・入力ファイル名(akizuki.mbox)、出力ファイル名(history.txt)、開始パターン(【ご注文者】)、終了パターン(【お支払方法】)、日付パターン(Date:.*)それから区切り(---\n)なんかを改変すると他の用途にも使えるかもしれない。パターンについては全て正規表現として扱われるので、半角記号とかはエスケープする必要があるかも。

・以上、注文履歴をそのまんま書き出すでござるの巻。このままでもまあまあ便利だと思うけど、次はいったんCSVにしてからもう少し加工していきたい。つづく。

・あ、これ、次のをすぐに書かなきゃいけないやつ。

*1:左のチェックボックスにチェックを入れ、上部の「ラベル」アイコン→新規作成で新しいラベルを作る。

*2:まず「選択をすべて解除」し、Ctrl+F等からGmail(メール)を検索、右のチェックボックスにチェックを入れ、「メールのすべてのデータが含まれます」をクリック→「メールのすべてのメッセージを含める」を解除→「すべて選択」の位置を2回クリックするなどしてすべて解除→該当するラベルにチェックを入れる→OK→一番下の「次のステップ」→エクスポート先などを設定→「エクスポートを作成」をクリック。そんでしばらく待つ。

明けまして新しいはんだごてを買った

・はんだごておめでとう。

・しばらくHAKKOのPRESTOという温調のない急速加熱つきはんだごてを使っていてこれもまあまあ便利だとは思うんだけど、やっぱり立ち上がりの加熱にどうしても時間がかかってしまうのが俺をはんだづけ作業から遠ざけていたし、それと同時に作業の失敗も誘っていた。いったん電源を入れたら修正までぜんぶやらないと次に電源を入れるときにまた待ち時間が生じてしまうからだ。

・今回は念入りに下調べをしたよ。結局、セラミックヒーター方式で熱容量の大きいこて先というお決まりのパターンがいけないんだという結論に至った。どうしても熱容量は必要ではないかと思ってしまうところだが、実はデジタル温調の精度と加熱の能力がしっかりしていれば温度が下がる側からどんどん加熱するはずだからその方が問題が少ないのではないか。

・そこでたどり着いたのが、JBCの規格C210とC245、それからHAKKOの規格T12。最近よく「意外といい」と耳にするUSBはんだごてなんかも同じ方式なんだと思うけど、このへんのはヒータがこて先の先端付近?に内蔵されていて加熱がめっちゃ早いらしい。C210は2秒ではんだが溶けるとか言ってる。

・で、色々値段とかも鑑みてT12-942というT12規格の互換機にした。むろん中国メーカの製品だ。12月27日にAliExpressで注文して(ちなみにAliExpressでは初注文)、同日中国から出荷されて元日に届いた。配送や通関に携わる方々には感謝しかない。

・一応ステーション型で、ステーションのサイズは90×40×40⋯⋯ってあんまり似てる大きさのものが思いつかないんだけど、チョコボールの箱を3個重ねたくらいかなあ⋯⋯というなかなかのミニサイズ。

・もちろんデジタル温調で、表示されている温度と実際のこて先温度との差も小さいっぽい。電源を入れてからはんだが溶けるまで、さすがに2秒とはいかないが、だいたい6~7秒といったところか。夏はもっと速いだろう。

・スリープ機能やブースト機能なんかもあって、スリープに至る時間(デフォルトは30秒)や、ブーストの温度(デフォルトは+50℃)やボタンを押してからブーストが終わるまでの時間(デフォルトは30秒)は調整可能。スリープはステーションのボタンを押すか、こて部に内蔵されている何らかのセンサが反応すると解除されるみたいなのだが、このセンサの正体がよくわからん。とにかくはんだづけ中でも平気でスリープに入るので、そのたびにこて部を振ったりするのが面倒だ。そもそも360℃程度にしておくならそんなにきっちりスリープしなくてもいいんじゃないかと思う。5分くらいに設定しておくことにしよう。

・でもお高いんでしょう? ご安心くださいそこはAliExpress価格、今なら異なる種類のこて先5本がついてきて、堂々の3,360円でございます。ただし電源は付属しておりませんので、24V4Aの電源を別途ご用意ください。俺も同時に注文したんだけど電源が届くのが数日後だったので、それまでは安定化電源で運用した。Φ2.1/5.5のセンタープラスでおk。

・↓Amazonでも4000円程度で売ってるようだ。これも電源ついてないみたいね。

・っていうか、特にこういう電熱関係の機器は電源が内蔵されてない方が安心だったりするんだよね。ほら、AC100Vを採用してる国って日本くらいしかないわけじゃん⋯?