C# - 解析网页的最佳方法?

Posted

技术标签:

【中文标题】C# - 解析网页的最佳方法?【英文标题】:C# - Best Approach to Parsing Webpage? 【发布时间】:2010-09-22 22:48:13 【问题描述】:

我已将整个网页的 html 保存为字符串,现在我想从链接中获取“href”值,最好能够稍后将它们保存为不同的字符串。最好的方法是什么?

我尝试将字符串另存为 .xml 文档并使用 XPathDocument 导航器对其进行解析,但是(令人惊讶的是)它不能很好地导航非真正的 xml 文档。

正则表达式是实现我想要实现的目标的最佳方法吗?

【问题讨论】:

【参考方案1】:

我可以推荐HTML Agility Pack。我曾在一些需要解析 HTML 的情况下使用它,而且效果很好。将 HTML 加载到其中后,您可以使用 XPath 表达式来查询文档并获取锚标记(以及其中的任何其他内容)。

HtmlDocument yourDoc = // load your HTML;
int someCount = yourDoc.DocumentNode.SelectNodes("your_xpath").Count;

【讨论】:

哇,太棒了... :) 我本来打算写一个 HTML 解析器...但现在我不需要再这样做了...非常感谢 Jeff【参考方案2】:

正则表达式是一种方法,但它可能会出现问题。

大多数 HTML 页面无法使用标准 html 技术进行解析,因为正如您所发现的,大多数页面不进行验证。

您可以花时间尝试集成 HTML Tidy 或类似工具,但只构建您需要的正则表达式会快得多。

更新

在本次更新时,我收到了 15 票赞成票和 9 票反对票。我认为也许人们没有阅读这个问题的问题,也没有阅读这个答案的 cmets。 OP 想要做的就是获取 href 值。 就是这样。从这个角度来看,一个简单的正则表达式就可以了。如果作者想解析其他项目,那么我不会像开头所说的那样推荐正则表达式,充其量是有问题的。

【讨论】:

好答案 - 正则表达式是你的朋友! 错误答案。不要这样做。 -1 嗯,使用正则表达式解析 HTML。什么可能出错?哦对了:***.com/questions/1732348/… 尝试使用 RegEx 解析所有标签是个坏主意吗?是的。但是,正则表达式的构建是为了从字符串中获取所有 href="whatever" 值。这就是 OP 想要做的 确保边缘情况可能发生——比如当模式存在于文本节点中时——但正则表达式可能是一个足够好的解决方案,并且实现起来非常容易和快速。【参考方案3】:

为了处理各种形状和大小的 HTML,我更喜欢使用 HTMLAgility 包@http://www.codeplex.com/htmlagilitypack,它允许您针对所需节点编写 XPath,并在集合中获取这些返回。

【讨论】:

【参考方案4】:

您可能想要 Majestic 解析器之类的东西:http://www.majestic12.co.uk/projects/html_parser.php

还有一些其他选项可以处理易碎的 html。正如其他人所提到的,Html Agility Pack 值得一看。

我不认为正则表达式是 HTML 的理想解决方案,因为 HTML 不是上下文无关的。如果不精确,它们可能会产生足够的结果;甚至确定性地识别 URI 也是一个麻烦的问题。

【讨论】:

【参考方案5】:

如果可能的话,最好不要重新发现***。有一些很好的工具可以将 HTML 转换为格式良好的 XML,或者充当 XmlReader:

这里有三个很好的工具:

    TagSoup是一个开源程序,是一个基于Java和SAX的工具,由John Cowan开发。这是 一个用 Java 编写的符合 SAX 的解析器,它不是解析格式良好或有效的 XML,而是解析在野外发现的 HTML:糟糕、肮脏和野蛮,尽管通常很不短。 TagSoup 是为那些必须使用某种看似合理的应用程序设计来处理这些东西的人设计的。通过提供 SAX 接口,它允许将标准 XML 工具应用于甚至最糟糕的 HTML。 TagSoup 还包括一个命令行处理器,它读取 HTML 文件并可以生成干净的 HTML 或格式良好的 XML,它与 XHTML 非常接近。Taggle 是 TagSoup 的商业 C++ 端口。

    SgmlReader是微软Chris Lovett开发的工具。 SgmlReader 是任何 SGML 文档(包括对 HTML 的内置支持)的 XmlReader API。还提供了一个命令行实用程序,用于输出格式正确的 XML 结果。 下载包含独立可执行文件和完整源代码的 zip 文件:SgmlReader.zip

    一个杰出的成就是the pure XSLT 2.0 Parser of HTML写的David Carlisle

阅读它的代码对我们每个人来说都是一个很好的学习练习。

来自描述:

"d:htmlparse(字符串) d:htmlparse(string,namespace,html-mode) 单参数形式等价于) d:htmlparse(string,'http://ww.w3.org/1999/xhtml',true())) 使用一些内置的启发式方法将字符串解析为 HTML 和/或 XML) 控制元素的隐含打开和关闭。 它没有完整的 HTML DTD 知识,但有完整的列表 空元素和实体定义的完整列表。 HTML 实体,以及 十进制和十六进制字符引用都被接受。注意 html-entities 即使 html-mode=false() 也会被识别。 元素名称是小写的(如果 html-mode 为 true())并放入 命名空间参数指定的命名空间(可能是“”来表示 没有命名空间,除非输入有明确的命名空间声明,在 在这种情况下,这些将受到尊重。 如果 html-mode=true()"

则属性名称为小写

阅读更详细的描述here

希望这会有所帮助。

干杯,

迪米特·诺瓦切夫。

【讨论】:

【参考方案6】:

我同意 Chris Lively 的观点,因为 HTML 通常不是很好的格式,您最好使用正则表达式。

href=[\"\'](http:\/\/|\.\/|\/)?\w+(\.\w+)*(\/\w+(\.\w+)?)*(\/|\?\w*=\w*(&\w*=\w*)*)?[\"\']

来自 RegExLib 上的 here 应该可以帮助您入门

【讨论】:

感谢时间。我正在尝试使用它,但是,C# 一直告诉我所有的反斜杠都是“无法识别的转义序列”。在那里扔一个@也无济于事。你知道发生了什么吗? 哈哈,我的意思是“谢谢蒂姆”。时间不值得任何感谢。 这个链接帮我弄明白了regexadvice.com/forums/thread/36529.aspx 这是因为 HTML 格式不正确,您不应该使用 RegEx:***.com/questions/1732348/… 我同意一般情况,解析 HTML 比任何人预期的要困难得多,而且对于单独的正则表达式来说也太难了,但是......在这种特定情况下,只解析 href,正则表达式很好,比 XML DOM 更容易【参考方案7】:

如果您知道或可以将文档修复为至少格式正确,那么您可能会更幸运地使用 xml。如果你有 good html(或者更确切地说是 xhtml),.Net 中的 xml 系统应该能够处理它。不幸的是,好的 html 非常罕见。

另一方面,正则表达式在解析 html 时真的很糟糕。幸运的是,您不需要处理完整的 html 规范。您需要担心的是解析 href= 字符串以获取 url。即使这可能很棘手,所以我不会马上尝试。相反,我将首先提出一些问题,以尝试建立一些基本规则。它们基本上都归结为“您对文档了解多少?”,但这里是:

您知道“href”文本是否总是小写? 您知道它是否总是在 url 周围使用双引号、单引号或什么都不加? 它是否始终是有效的 URL,或者您是否需要考虑诸如“#”、javascript 语句等内容? 是否可以处理内容描述 html 功能的文档(即:href= 也可以在文档中,但不属于锚标记)? 关于该文档,您还能告诉我们什么?

【讨论】:

我知道 href 文本总是小写的。它将始终使用双引号。它可能总是有效的 URL,也可能不总是有效的 URL,但我假设它在 99% 的时间里都是有效的。该文档有可能在其他地方拥有“href”。这就是我能想到的。解析函数真的会比正则表达式更好吗? 这里的杀手是允许 href= 其他地方。它让您返回寻找真正的锚标记,这意味着您最好使用(非常宽松的)解析库。您甚至可以尝试将其加载到网络浏览器控件中。【参考方案8】:

我在这里链接了一些代码,可以让您使用“LINQ to HTML”...

Looking for C# HTML parser

【讨论】:

以上是关于C# - 解析网页的最佳方法?的主要内容,如果未能解决你的问题,请参考以下文章

在 C# 中解析 html 的最佳方法是啥? [关闭]

在 C# 代码中解析(大)XML 的最佳方法是啥?

在 C# 中解析大型 XML(大小为 1GB)的最佳方法是啥?

.Net(C#) 对网页加载后解析后的内容截图或生成pdf文件的方法

解析 HTTP JSON 响应 - C# [重复]

从 web delphi 中提取信息的最佳方法