19

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

我已经尝试将字符串保存为 .xml 文档并使用 XPathDocument 导航器对其进行解析,但是(令人惊讶的是)它不能很好地导航一个 not-really-an-xml-document。

正则表达式是实现我想要完成的最佳方式吗?

4

8 回答 8

45

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

HtmlDocument yourDoc = // load your HTML;
int someCount = yourDoc.DocumentNode.SelectNodes("your_xpath").Count;
于 2008-11-18T22:10:04.520 回答
10

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

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

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

更新

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

于 2008-11-18T21:49:26.120 回答
5

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

于 2008-11-18T22:05:53.967 回答
2

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

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

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

于 2008-11-18T21:57:32.627 回答
2

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

这里有三个很好的工具:

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

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

  3. 一项杰出的成就是由David Carlisle编写的纯 XSLT 2.0 HTML 解析器

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

从描述:

" d:htmlparse(string)
 d:htmlparse(string,namespace,html-mode)

  单参数形式等价于)
  d:htmlparse(string,' http://ww.w3.org/1999/xhtml ',true ()))

  使用一些内置的启发式将字符串解析为 HTML 和/或 XML 以)
  控制元素的隐含打开和关闭。

  它不具备 HTML DTD 的完整知识,但具有
  空元素的完整列表和实体的完整列表定义。HTML 实体,以及
  十进制和十六进制字符引用都被接受。注意
  ,即使 html-mode=false(),html-entities 也会被识别。

  元素名称是小写的(如果 html-mode 为 true())并放入
  由命名空间参数指定的命名空间(可能是“”以表示
  无命名空间,除非输入有明确的命名空间声明,在
  这种情况下,这些将被尊重。

  如果 html-mode=true(),属性名称将小写

在此处阅读更详细的说明。

希望这有帮助。

干杯,

迪米特雷·诺瓦切夫。

于 2008-11-19T03:37:58.103 回答
1

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

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

这里开始 RegExLib 应该让你开始

于 2008-11-18T22:02:01.790 回答
0

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

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

  • 你知道“href”文本是否总是小写吗?
  • 你知道它是否总是在 url 周围使用双引号、单引号或什么都不用?
  • 它是否始终是一个有效的 URL,或者您是否需要考虑诸如“#”、javascript 语句之类的内容?
  • 是否可以使用内容描述 html 功能的文档(IE:href=也可以在文档中并且不属于锚标记)?
  • 关于该文件,您还能告诉我们什么?
于 2008-11-18T21:56:26.217 回答
0

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

寻找 C# HTML 解析器

于 2009-03-08T22:13:52.307 回答