在加载 MSHTML 文档之前删除无效的 URL
Removing invalid URLs from MSHTML document before it is loaded
我使用 MSHTML (IHTMLDocument
) 显示离线 HTML 其中可能包含各种链接。这些是从电子邮件 HTML.
加载的
其中一些有 URL 以 // 或 / 开头,例如:
<img src="//www.example.com/image.jpg">
<img src="/www.example.com/image.jpg">
这需要很多时间来解析和显示文档,因为它显然找不到 URL 因为它不是以 http:// 或 https://
开头
我尝试将 <base>
标记注入 <head>
并添加一个本地已知文件夹(该文件夹为空),这样就解决了这个问题。例如:
<base href="C:\myemptypath\">
但是,如果链接以 \\(UNC 路径)开头,同样的问题和较长的加载时间再次开始。喜欢:
<img src="\www.something.com\image.jpg">
我还尝试将 WebBrowser
控件置于“离线”模式以及我能想到但无法想出任何缺少 RegEx 的所有其他技巧并替换 [=56= 中的所有链接] 这将是非常缓慢的解决方案(或者我自己解析 HTML 这违背了 MSHTML 的目的)。
有没有办法:
在加载文档之前检测到这些无效的URL? - 注意:我已经通过 DOM 进行了导航,例如WebBrowser1.Document.body.all
集合,从所有标签获取所有可能的链接并修改它们,这很有效,但它只发生在文档已经加载之后,所以加载放弃之前的漫长等待时间仍在发生
可能会触发一些事件以避免加载这些无效链接,并简单地将它们替换为 about:blank
或空 ""
文本,例如某种“OnURLPreview " 我可以检查并拒绝加载无效的 URL 的事件?只有 OnDownloadBegin
事件不是它。
尽管我使用的是Delphi和C++(C++ Builder),但我欢迎任何语言的任何示例,因为我只需要这里的原理在哪个方向看。
经过很长一段时间,这是我使用的解决方案:
创建了一个 CLSID_HTMLDocument
的实例来解析 HTML:
DelphiInterface<IHTMLDocument2> diDoc;
OleCheck(CoCreateInstance(CLSID_HTMLDocument, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&diDoc)));
使用Document->write
将IHTMLDocument2
写入diDoc
// Creates a new one-dimensional array
WideString HTML = "Example HTML here...";
SAFEARRAY *psaStrings = SafeArrayCreateVector(VT_VARIANT,0,1);
if (psaStrings)
{
VARIANT *param;
BSTR bstr = SysAllocString(HTML.c_bstr());
SafeArrayAccessData(psaStrings, (LPVOID*)¶m);
param->vt = VT_BSTR;
param->bstrVal = bstr;
SafeArrayUnaccessData(psaStrings);
diDoc->write(psaStrings);
diDoc->close();
// SafeArrayDestroy calls SysFreeString for each BSTR
//SysFreeString(bstr); // SafeArrayDestroy should be enough
SafeArrayDestroy(psaStrings);
return S_OK;
}
解析 diDoc
中不需要的链接
DelphiInterface<IHTMLElementCollection> diCol;
if (SUCCEEDED(diDoc->get_all(&diCol)) && diCol)
{
// Parse IHTMLElementCollection here...
}
将解析的 HTML 提取到 WideString
并将 write
提取到 TWebBrowser
DelphiInterface<IHTMLElement> diBODY;
OleCheck(diDoc->get_body(&diBODY));
if (diBODY)
{
DelphiInterface<IHTMLElement> diHTML;
OleCheck(diBODY->get_parentElement(&diHTML));
if (diHTML)
{
WideString wsHTML;
OleCheck(diHTML->get_outerHTML(&wsHTML));
// And finally use the `Document->write` like above to write into your final TWebBrowser document here...
}
}
我使用 MSHTML (IHTMLDocument
) 显示离线 HTML 其中可能包含各种链接。这些是从电子邮件 HTML.
其中一些有 URL 以 // 或 / 开头,例如:
<img src="//www.example.com/image.jpg">
<img src="/www.example.com/image.jpg">
这需要很多时间来解析和显示文档,因为它显然找不到 URL 因为它不是以 http:// 或 https://
开头我尝试将 <base>
标记注入 <head>
并添加一个本地已知文件夹(该文件夹为空),这样就解决了这个问题。例如:
<base href="C:\myemptypath\">
但是,如果链接以 \\(UNC 路径)开头,同样的问题和较长的加载时间再次开始。喜欢:
<img src="\www.something.com\image.jpg">
我还尝试将 WebBrowser
控件置于“离线”模式以及我能想到但无法想出任何缺少 RegEx 的所有其他技巧并替换 [=56= 中的所有链接] 这将是非常缓慢的解决方案(或者我自己解析 HTML 这违背了 MSHTML 的目的)。
有没有办法:
在加载文档之前检测到这些无效的URL? - 注意:我已经通过 DOM 进行了导航,例如
WebBrowser1.Document.body.all
集合,从所有标签获取所有可能的链接并修改它们,这很有效,但它只发生在文档已经加载之后,所以加载放弃之前的漫长等待时间仍在发生可能会触发一些事件以避免加载这些无效链接,并简单地将它们替换为
about:blank
或空""
文本,例如某种“OnURLPreview " 我可以检查并拒绝加载无效的 URL 的事件?只有OnDownloadBegin
事件不是它。
尽管我使用的是Delphi和C++(C++ Builder),但我欢迎任何语言的任何示例,因为我只需要这里的原理在哪个方向看。
经过很长一段时间,这是我使用的解决方案:
创建了一个 CLSID_HTMLDocument
的实例来解析 HTML:
DelphiInterface<IHTMLDocument2> diDoc;
OleCheck(CoCreateInstance(CLSID_HTMLDocument, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&diDoc)));
使用Document->write
IHTMLDocument2
写入diDoc
// Creates a new one-dimensional array
WideString HTML = "Example HTML here...";
SAFEARRAY *psaStrings = SafeArrayCreateVector(VT_VARIANT,0,1);
if (psaStrings)
{
VARIANT *param;
BSTR bstr = SysAllocString(HTML.c_bstr());
SafeArrayAccessData(psaStrings, (LPVOID*)¶m);
param->vt = VT_BSTR;
param->bstrVal = bstr;
SafeArrayUnaccessData(psaStrings);
diDoc->write(psaStrings);
diDoc->close();
// SafeArrayDestroy calls SysFreeString for each BSTR
//SysFreeString(bstr); // SafeArrayDestroy should be enough
SafeArrayDestroy(psaStrings);
return S_OK;
}
解析 diDoc
DelphiInterface<IHTMLElementCollection> diCol;
if (SUCCEEDED(diDoc->get_all(&diCol)) && diCol)
{
// Parse IHTMLElementCollection here...
}
将解析的 HTML 提取到 WideString
并将 write
提取到 TWebBrowser
DelphiInterface<IHTMLElement> diBODY;
OleCheck(diDoc->get_body(&diBODY));
if (diBODY)
{
DelphiInterface<IHTMLElement> diHTML;
OleCheck(diBODY->get_parentElement(&diHTML));
if (diHTML)
{
WideString wsHTML;
OleCheck(diHTML->get_outerHTML(&wsHTML));
// And finally use the `Document->write` like above to write into your final TWebBrowser document here...
}
}