2020年4月12日日曜日

Emacs batch mode と HTML解析

前提

  • たくさんあるhtmlファイルの加工、編集をしたい。
  • 環境はWindows 10.
  • Emacsは入ってます。バージョン26.3.
  • MSYS2も入っていてBash使用可能。
  • しかしPython等のお手軽スクリプト言語の実行環境は無し。MicrosoftのPowershellやその他スクリプト言語には不慣れ。

ということでEmacsのDOM処理用関数を使うワンライナーを書くことにしました。


例題

カレントディレクトリにある拡張子htmlのファイルを開いてid="my-content"をもつ要素だけを抽出し、テキスト化して拡張子.txtのファイルに保存する、というもの。

for f in *.html; do
/c/Users/${user}/local/emacs-26.3-x86_64/bin/emacs --batch $f --eval='(princ (dom-texts (dom-by-id (libxml-parse-html-region (point-min) (point-max)) "my-content") "\n"))' > $f.txt;
done
  • "/c/Users/${user}/local/emacs-26.3-x86_64/bin/emacs": Windows上のemacsコマンドのパス
  • "--batch": Emacsバッチモード。バッチモードの定義は下記参考ページに書いてある。大雑把には、普段「バッファ」や「ウィンドウ」を使用するEmacsの入出力関数(message, princなど)を標準入力や標準出力、標準エラー出力に結び付けて、非インタラクティブに処理を実行する。
  • "--batch"直後の$fは処理対象のhtmlファイルで、非インタラクティブなEmacsはこのファイルを開いてバッファに読み込む。
  • "--eval"の引数としてelispコードを渡す。この例ではhtmlを開いたバッファ全体を"libxml-parse-html-region"関数に渡してDOM化し、次のそのDOMから"my-content"というidをもつ要素を"dom-by-id"関数で選び、選ばれた要素を"dom-texts"関数に渡してテキスト部分を抽出して"princ"で出力している。どの関数もEmacs標準のものだから外部のelispは利用していない。