将字符串转换为HTML文档

39

我正在使用WebClient.DownloadString(url)通过URL获取HTML文档,但很难找到我要查找的元素内容。在阅读相关文章时,我注意到了HtmlDocument及其具有的诸如GetElementById之类的便捷功能。如何使用由url返回的HTML填充HtmlDocument


32
不尝试正则表达式,点赞。 - SLaks
@SLaks 为什么这样? - corei11
1
@corei11:https://dev59.com/X3I-5IYBdhLWcg3wq6do#1732454 - SLaks
7个回答

33

使用Html Agility Pack,如SLaks所建议的那样,这变得非常简单:

string html = webClient.DownloadString(url);
var doc = new HtmlDocument();
doc.LoadHtml(html);

HtmlNode specificNode = doc.GetElementById("nodeId");
HtmlNodeCollection nodesMatchingXPath = doc.DocumentNode.SelectNodes("x/path/nodes");

32

HtmlDocument 类是对本地 IHtmlDocument2 COM 接口的封装。
无法直接通过字符串轻松创建它。

应该使用 HTML Agility Pack


3
由于 @dhsto 给出了准确的答案,我无法看出这个答案如何是正确的。 - ThunderGr

24
回答原问题:
HTMLDocument doc = new HTMLDocument();
IHTMLDocument2 doc2 = (IHTMLDocument2)doc;
doc2.write(fileText);
// now use doc

然后将其转换回字符串:

doc.documentElement.outerHTML;

2
似乎不可能像那样实例化HTMLDocument - Steinfeld
2
@Steinfeld 我刚刚又进行了一次测试,对我来说是有效的。请确保你正在使用 mshtml;。在引用对话框中它是 Microsoft.mshtml。我正在使用版本 7.0.3300 - David Sherret
谢谢,我几个小时前就完成了,确实有效。不过我尝试了敏捷包,它似乎更加“用户友好” =] - Steinfeld
1
@Steinfeld,没错,它确实是!Mshtml库非常麻烦,但对于做一些简单的事情来说已经足够了。 - David Sherret
这个可以工作,但它会尝试在我的环境中打开一个外部的 about:blank 页面。 - hillin
@hillin 非常奇怪。我从未遇到过这种情况。 - David Sherret

20

如果您不想使用HTML Agility Pack,并且只想使用本地的.NET代码从字符串中获取HtmlDocument,则可以参考这篇文章如何将字符串转换为HtmlDocument

以下是可用的代码块

public System.Windows.Forms.HtmlDocument GetHtmlDocument(string html)
        {
            WebBrowser browser = new WebBrowser();
            browser.ScriptErrorsSuppressed = true;
            browser.DocumentText = html;
            browser.Document.OpenNew(true);
            browser.Document.Write(html);
            browser.Refresh();
            return browser.Document;
        }

我不再在.NET环境中工作,因此无法测试是否有效。但是,如果社区中的其他人可以验证这一点,我将很高兴接受它作为答案。感谢您多年来的关注!XD - lappy
其实我一直在寻找这个解决方案,但是没有找到不用第三方库的方法。最终这段代码解决了我的问题,并且我在我的应用中使用了它。希望这会对像我一样的一些人有所帮助:) - Nikhil Gaur

4

我对Nikhil的回答进行了一定程度的改编,以简化它。不可否认,我没有通过.net编译器运行它,而Nikhil放置的几行代码可能有非常好的原因,但是至少在我的用例中(一个非常简单的页面),它们是不必要的。

我的用例是为了快速编写powershell脚本:

$htmlText = $(New-Object 
System.Net.WebClient).DownloadString("<URI HERE>") #Get the HTML document from a webserver
$browser = New-Object System.Windows.Forms.WebBrowser
$browser.DocumentText = $htmlText
$browser.Document.Write($htmlText)
$response = $browser.document

对于我的情况,这返回了一个包含HTMLElement对象的HTMLDocument对象,而不是在PS 5.1.14393.1944中由调用Invoke-WebRequest返回的__ComObject对象类型(这些类型在powershell类代码中使用起来很具有挑战性)。
我认为等价的C#代码是:
public System.Windows.Forms.HtmlDocument GetHtmlDocument(string html)
{
    WebBrowser browser = new WebBrowser();
    browser.DocumentText = html;
    browser.Document.Write(html);
    return browser.Document;
}

这很好,但你需要运行以下命令: [void][reflection.assembly]::LoadWithPartialName("System.Windows.Forms") 才能创建 System.Windows.Forms.WebBrowser 对象。 - Frank Lesniak
@Frank Lesniak 你确定那不是版本相关的吗?除非我调用的是不在 .net 程序集缓存中的 DLL,我不需要使用 loadwithpartialname。我在这段代码中肯定没有使用它(PowerShell 版本)。 或者你是说对于 C# 代码,这个调用是必要的吗?我本来期望有一个项目库和一个 using 语句。 - Takophiliac
嘿,Takophiliac,你可能有所发现。在PowerShell 5.1上,我也可以创建一个新的System.Net.WebClient对象。不幸的是,我不记得我当时测试的版本是什么了...但我经常进行向下兼容的工作,所以很可能是PowerShell v1或v2。 - Frank Lesniak

2

您可以通过以下方式获取HTML文档:

 System.Net.WebClient wc = new System.Net.WebClient();

 System.IO.Stream stream = wc.OpenRead(url);
 System.IO.StreamReader reader = new System.IO.StreamReader(stream);
 string s = reader.ReadToEnd();

 HtmlDocument doc = new HtmlDocument();
 doc.LoadHtml(s);

你已经有了getbiyid和getbyname...但是如果需要更深入的操作,建议使用HTML Agility Pack。例如:你可以使用doc.DocumentNode.SelectNodes(xpathselector)或者正则表达式解析文档。

顺便问一下:为什么不用正则表达式?如果你能正确使用它,它非常酷。但是xpath也非常强大。所以“选择你的毒药”。

再见


2
HtmlDocument 对象好像没有 .LoadHtml() 方法。 - Photonic
@Photonic 但对我来说是可以的。在这里工作。 - C4d
2
@C4u,你的HtmlDocument在哪个命名空间中?我正在使用System.Windows.Forms.HtmlDocument,但没有LoadHtml()方法。 - Scott Baker
这就是它们的区别。它是 HtmlAgilityPack.HtmlDocument - C4d

0

但是您根本无法创建实例。这需要一个现有的实例。 - SLaks
我将以下代码放在窗体的Load事件处理程序中: webBrowser1.DocumentText = Properties.Resources.HtmlContent; - radsdau
@SLaks wb = new webbrower(); wb.DocumentText(""); htmldoc = wb.Document().OpenNew(true); htmldoc.Write("<html></html>"); <= 这对我来说完全没问题。 - MattyMatt

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接