HTMLの高度なパース

  • 概要

    IronPythonの例題のひとつとなります。

    少々崩れたHTMLデータであってもDOMとして解析し、要素の抽出や置き換えが可能な HTML Aglity Pack を利用したサンプルです。

    マネージドdll(.NET用DLL)だけ公開されているような「配布ライブラリ」を、
    hmPyを経由して、いかに手軽に秀丸マクロから利用するか、といったサンプルでもあります。

  • ダウンロード

    DOWNLOAD ⇒ HmHtmlAgility.zip v.1.20ファイル。
    └更新日 2017/04/08

    このhmHtmlAgility.zipには変換元のHTMLとなるサンプルファイルa.htmlが含まれています。

    説明

    HTMLの要素を解析し、その中身を取り出したい、といったことは珍しいことではありません。
    しかし、「フォーマット的に正しいことが期待できるXMLやRSS」とは異なり、
    HTMLは人の手が多分に混じっていることが多いため、不正なフォーマット(崩れた状態の)ものが多いの特徴です。
    (一つも誤りがないHTMLの方が珍しいことでしょう)

    IronPythonの部分

    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 ファイルに対して…

    • titleタグについては、中身のテキストだけに置き換える(タグを除去)
    • blockquoteタグについては、中身のHTMLだけに置き換える(一番外のblockquoteタグだけを除去)

    それを 元のファイル名 + 「_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;
        
  • ライセンス

    • HmHtmlAgility.pyとHmHtmlAgility.macについて

      パブリックドメインとします。(即ち利用は自由)

    • Html Agility Packについて

      Simon Mourierの著作物であり、Microsoft Public License(Ms-PL) ライセンスとなります。
      詳細はHtml Agility Packのライセンスを確認してください。