次の方法で共有


COMのHTMLFileでgetElementsByClassNameが使えなくなった。

質問

2021年2月24日水曜日 12:09

WScriptで下記のように、HTMLFileオブジェクトを生成してHTMLパースを実施し、getElementsByClassNameを利用して、要素を取得していました。

var doc = new ActiveXObject("HTMLFile");

しかしながら、2021/2/10ぐらいにWindowsがアップデートされてからエラーが出るようになりました。

エラー的にgetElementsByClassNameが存在しないような感じだったので、PowerShellを開いて下記のように実行し、mshtml.HTMLDocumentClassの要素を確認してみました。

$com = New-Object -ComObject HTMLFile

$com|Get-Member

確認してみると、IHTMLDocument5の要素までしか存在せず、IHTMLDocument8がありませんでした。(Get系の関数は下記だけでした。)

getElementById                                      Method     mshtml.IHTMLElement, Microsoft.mshtml, Version=7.0.3300.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a getElementById(string v), mshtml.IHTMLElement, Microsoft.mshtml, Version=7.0.3300.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a DispHTML...

getElementsByName                                   Method     mshtml.IHTMLElementCollection, Microsoft.mshtml, Version=7.0.3300.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a getElementsByName(string v), mshtml.IHTMLElementCollection, Microsoft.mshtml, Version=7.0.3300.0, Culture=neutral, PublicKeyToken=b0...

getElementsByTagName                                Method     mshtml.IHTMLElementCollection, Microsoft.mshtml, Version=7.0.3300.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a getElementsByTagName(string v), mshtml.IHTMLElementCollection, Microsoft.mshtml, Version=7.0.3300.0, Culture=neutral, PublicKeyToken...

GetHashCode                                         Method     int GetHashCode()

GetLifetimeService                                  Method     System.Object GetLifetimeService()

GetType                                             Method     type GetType()

IHTMLDocument8まで使えるようにしたい場合どのようにすればいいでしょうか。

もしくは、同様に使えるHTMLパーサーは何かあるでしょうか。

よろしくお願いします。

すべての返信 (10)

2021年2月27日土曜日 13:58 ✅回答済み | 1 票

documentModeというものを検索してみたのですが、変更の仕方がよく分りませんでした分りませんでした。

以前はまとまった資料がいろいろあったのですが、今となっては、Web 上からも情報が失われつつありますね…。

Web コンテンツの場合は、サーバー側で HTTPレスポンスヘッダ を指定するものですが、静的データの場合には、HTML コンテンツ内の meta タグでの指定となります。

使ってるテキストのhtmlファイルは無いですよ。

ファイルからでも良いですし、オンメモリでの書き込みでもよいので、 モード指定しましょう。

検;用コード。

var doc = new ActiveXObject("HTMLFile");
doc.write('');
WScript.Echo('==== 指定なし ====');
WScript.Echo('documentMode=>' ; doc.documentMode);
WScript.Echo('compatMode=>' ; doc.compatMode);
WScript.Echo('doctype=>' ; doc.doctype);
WScript.Echo('getElementsByClassName=>' ; doc.getElementsByClassName);
WScript.Echo('getElementsByName=>' ; doc.getElementsByName);

var lists = ['なし', '5', '7', 'EmulateIE7', '8', 'EmulateIE8', '9', 'EmulateIE9', '10', 'EmulateIE10', '11', 'EmulateIE11', 'Edge'];
for(var i = 0; i < lists.length; i;;) {
  var ie = lists[i];

  for (var j = 0; j <= 1; j;;) {
    var docType = (j == 0) ? '' : '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">';
    var meta = (ie == 'なし') ? '' : '<meta http-equiv="X-UA-Compatible" content="IE=' ; ie ; '">';

    WScript.Echo('==== 互換指定:' ; ie ; ' / DOCTYPE: ' ; ((j==0) ? 'なし' : 'あり') ; ' ====');

    doc = new ActiveXObject("HTMLFile");
    doc.write(docType ; '<html><head>' ; meta ; '</head><body></body></html>');
    WScript.Echo('documentMode=>' ; doc.documentMode);
    WScript.Echo('compatMode=>' ; doc.compatMode);
    WScript.Echo('doctype=>' ; doc.doctype);
    WScript.Echo('getElementsByClassName=>' ; doc.getElementsByClassName);
    WScript.Echo('getElementsByName=>' ; doc.getElementsByName);
  }
}
WScript.Quit();

2021年2月27日土曜日 18:56 ✅回答済み

ご回答ありがとうございます。

ウィンドウズスクリプトプログラマさんのコードと 魔界の仮面弁士さんのコメントを見て、下記のようなファイルを作成してみました。

test_getElementsByClassName.vbs

set doc=wscript.getobject("test_get.html")
msgbox "typename(doc): " & typename(doc)
msgbox "doc.documentMode: " & doc.documentMode
msgbox doc.getElementsByClassName("gettest").item(2).innerHtml

test_get.html

<!DOCTYPE html>
<html lang="pl">
    <head>
        <title>get test page</title>
        <meta http-equiv="X-UA-Compatible" content="IE=11" >
    </head>
    <body>
        <div class="gettest">項目1</div>
        <div>項目2</div>
        <div class="gettest">項目3</div>
        <div class="gettest">項目4</div>
    </body>
</html>

実行してみると、確かに「doc.documentMode: 11」と表示され、getElementsByClassNameも問題なく実行されました。

また、以前うまく取得できなかったページもVBScript.RegExpでheadタグを下記のように書き換えてやると、documentMode 11として実行出来ました。

<head><meta http-equiv="X-UA-Compatible" content="IE=11" ></head>

一点気になったのですが、test_get.htmlからmetaタグを削除すると、documentModeは7と表示されるようになりました。
X-UA-Compatibleは最新のIEに対応していないページにつけるタグのように見えるのですが、何も指定されていないhtmlはIE11で読み込むようには出来ないのでしょうか。


2021年2月27日土曜日 21:44 ✅回答済み | 1 票

X-UA-Compatibleは最新のIEに対応していないページにつけるタグのように見えるのですが、何も指定されていないhtmlはIE11で読み込むようには出来ないのでしょうか。

IE10までと違い。IE11からはデフォルトでdocumentModeは11になるように変更されています。ただしそれはInternet Explorerとしての挙動であって、COMオブジェクトの方は過去との互換もあり、一部異なる挙動をします。

念のため、ドキュメント モードの選択のフローチャートを参照し、documentModeを変更する設定が含まれていないか確認してみてください。

  • Site list <emie> section(エンタープライズモードなので違う)
  • Site list <docMode> section(なんだっけ? でもたぶん違う)
  • X-UA-Compatible meta tag(今話題になっている)
  • X-UA-Compatible header(ウィンドウズスクリプトプログラマさんが少し触れた、たぶん違う)
  • Microsoft Compat View list(これも違う)
  • Group Policy for IE5 and IE7
  • Local Compat View list
  • Internet setting
  • !DOCTYPE declared(どっちにしろIE11モードになるので違う)

HTMLFileの場合、直接ファイル生成していてURLがないという事情も踏まえると、このフローチャートのほとんどが該当しませんが、とはいえIE11モードでなくIE7モードに切り替える理由はこの中にあるかもしれません。


2021年2月28日日曜日 2:11 ✅回答済み | 1 票

© ウィンドウズスクリプトプログラマ - Windows Script Programmer 2021

<!DOCTYPE html>

があると、7。なければ、5。みたい。

有り無しでどう変わるかは、
IE11 でドキュメントモードが選択されていることを示すフルサイズのフローチャート - Internet Explorer | Microsoft Docs  これに書いてあるのかも。ie11もhtmlfileも;たようなものでしょう。

そういう話になると、Msdn フォーラム - Internet Explorer で聞いて。


2021年2月26日金曜日 0:56

© ウィンドウズスクリプトプログラマ - Windows Script Programmer 2021 デフォルトのdocumentModeが5のせいなのでは。

<meta http-equiv="X-UA-Compatible" content="IE=11" >
だと、あります。


2021年2月26日金曜日 13:13

回答ありがとうございます。

> デフォルトのdocumentModeが5のせいなのでは。

> <meta http-equiv="X-UA-Compatible" content="IE=11" >
> だと、あります。

documentModeというものを検索してみたのですが、変更の仕方がよく分りませんでした分りませんでした。

どこから変更すればいいのでしょうか。

よろしくお願いします。


2021年2月26日金曜日 13:58

© ウィンドウズスクリプトプログラマ - Windows Script Programmer 2021

ヘッダか、同等の<meta>

<meta http-equiv="X-UA-Compatible" content="IE=11" >

です。


2021年2月27日土曜日 12:02

使ってるテキストのhtmlファイルは無いですよ。

PowerShellで下記コマンドを打ち込んで、HTMLFILEオブジェクトのメンバー関数を確認しているだけなので。

$com = New-Object -ComObject HTMLFile

$com|Get-Member

 ウィンドウズスクリプトプログラマさんは、どのような操作をされて確認をされたのでしょうか。


2021年2月27日土曜日 13:09 | 1 票

© ウィンドウズスクリプトプログラマ - Windows Script Programmer 2021

vbsですが、

set doc=wscript.getobject("C:\   \a.htm")
msgbox typename(doc)
msgbox doc.documentMode
msgbox doc.getElementsByClassName("a")


2021年2月28日日曜日 14:25

皆さん、ご回答ありがとうございます。

ツリーを見てみると、F12 tools docmodeoverrideが多分一番近そうですが、comオブジェクトに対して設定出来そうなものは見つけられませんでした、

ひと先ず、読み込むHTMLソースにX-UA-Compatibleを追加することで対処しようと思います。

ありがとうございました。