IronPythonの例題のひとつとなります。
少々崩れたHTMLデータであってもDOMとして解析し、要素の抽出や置き換えが可能な HTML Aglity Pack を利用したサンプルです。
マネージドdll(.NET用DLL)だけ公開されているような「配布ライブラリ」を、
hmPyを経由して、いかに手軽に秀丸マクロから利用するか、といったサンプルでもあります。
このhmHtmlAgility.zipには変換元のHTMLとなるサンプルファイルa.htmlが含まれています。
HTMLの要素を解析し、その中身を取り出したい、といったことは珍しいことではありません。
しかし、「フォーマット的に正しいことが期待できるXMLやRSS」とは異なり、
HTMLは人の手が多分に混じっていることが多いため、不正なフォーマット(崩れた状態の)ものが多いの特徴です。
(一つも誤りがないHTMLの方が珍しいことでしょう)
IronPythonの部分では、HTML Agility Packを利用しつつ、
「HTMLのロード」「toInnerText」「toInnerHtml」「新たなHTMLへのセーブ」という4つの関数に分けて制作してみました。 秀丸マクロから呼び出されることを意識したインターフェイスと言えるでしょう。
#coding: cp932 DEBUG = 1 import clr import sys sys.path.append(hm.Macro.Var["currentmacrodirectory"]) import System import System.IO import System.Text import System.Collections.Generic clr.AddReferenceByPartialName( "HtmlAgilityPack") clr.AddReferenceByPartialName( "System.Windows.Forms" ) from HtmlAgilityPack import * from System.Collections.Generic import * load_html_filename = hm.Macro.Var["$load_html_filename"] save_html_filename = hm.Macro.Var["$save_html_filename"] file_encode = hm.Macro.Var["#encode"] doc = "" # htmlのロード。秀丸から操作しやすくするためにこのような単純なインターフェイスで def LoadHTML(): global doc si = None try: si = System.IO.StreamReader( load_html_filename, System.Text.Encoding.GetEncoding(file_encode) ) except: System.Windows.Forms.MessageBox.Show("load_html_filename中にエラーが発生しました") if si: si.Close() raise IOError doc = HtmlDocument() doc.LoadHtml(si.ReadToEnd()) si.Close() # 対象のタグの中身はテキストだけになる(タグも除去される) def toInnerText(tag): global doc q = doc.DocumentNode.Descendants(tag) l = List[HtmlNode](q) for item in l: newNodeStr = item.InnerText newNode = HtmlNode.CreateNode(newNodeStr) item.ParentNode.ReplaceChild(newNode, item) # 対象のタグは除去するが、他のタグは残る def toInnerHtml(tag): global doc q = doc.DocumentNode.Descendants(tag) l = List[HtmlNode](q) for item in l: newNodeStr = item.InnerHtml newNode = HtmlNode.CreateNode(newNodeStr) item.ParentNode.ReplaceChild(newNode, item) # htmlのセーブ。秀丸から操作しやすくするためにこのような単純なインターフェイスで def SaveHTML(): global doc try: so = System.IO.StreamWriter( save_html_filename, False, System.Text.Encoding.GetEncoding(file_encode) ) so.Write(doc.DocumentNode.InnerHtml) so.Close() except: System.Windows.Forms.MessageBox.Show("save_html_filename中にエラーが発生しました") if so: so.Close() raise IOError
マクロ側では「ロードファイル」や「セーブファイル」を指定することとなるでしょう。
今回はエンコーディングについては、「UTF-8」固定としました。
ローカルなどの作業用テキストなどとは異なり、
Web用のHTMLについては、近年では様々な都合により、ほとんどのケースでUTF-8で記述されているようです。
マクロとして開いている html ファイルに対して…
それを 元のファイル名 + 「_up.html」という形にして秀丸で開いています。
#PY = loaddll( hidemarudir + "\\hmPY.dll" ); if (!#PY) { message("hmPYが未導入"); } $load_html_filename = filename2; $save_html_filename = directory2 + "\\" + basename2 + "_up.html"; #encode = codepage; #_ = dllfuncw( #PY, "DoFile", currentmacrodirectory + "\\hmHtmlAgility.py" ); #_ = dllfuncw( #PY, "DoString", R"IPY( LoadHTML() toInnerText('title') toInnerHtml('blockquote') SaveHTML() )IPY" ); freedll( #PY ); openfile $save_html_filename;
パブリックドメインとします。(即ち利用は自由)
Simon Mourierの著作物であり、Microsoft Public License(Ms-PL) ライセンスとなります。
詳細はHtml Agility Packのライセンスを確認してください。