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

时间:2008-11-18 21:46:36

标签: c# html xml html-content-extraction

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

我尝试将字符串保存为.xml文档并使用XPathDocument导航器进行解析,但是(惊喜的是)它并没有很好地导航非真正的xml文档。

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

8 个答案:

答案 0 :(得分:45)

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

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

答案 1 :(得分:10)

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

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

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

<强>更新

在此次更新时,我收到了15个up和9个downvotes。我想也许人们不是在阅读这个问题,也不是对这个答案的评论。 OP想要做的就是获取href值。 就是这样。从这个角度来看,一个简单的正则表达式就好了。如果作者想要解析其他项目,那么就像我在开头所说的那样,我无法推荐正则表达式,这在最好的情况下是有问题的。

答案 2 :(得分:5)

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

答案 3 :(得分:2)

可能你想要像Majestic解析器这样的东西:http://www.majestic12.co.uk/projects/html_parser.php

还有一些其他选项可以处理片状html。正如其他人提到的那样,Html Agility Pack值得一看。

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

答案 4 :(得分:2)

总是更好,如果可能的话,不要重新发现轮子。存在一些好的工具,可以将HTML转换为格式良好的XML,也可以充当XmlReader:

以下是三个好工具:

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

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

  3. 杰出成就the pure XSLT 2.0 Parser of HTMLDavid Carlisle撰写。

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

    来自说明:

    d:htmlparse(字符串)
    d:htmlparse(字符串,命名空间,HTML模式)

    一个论证形式相当于) d:htmlparse(字符串, 'http://ww.w3.org/1999/xhtml',真()))

    使用一些内置的启发式方法将字符串解析为HTML和/或XML 控制暗示元素的开启和关闭。

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

    元素名称是小写的(如果html-mode为true())并放入
    命名空间参数指定的命名空间(可能是“”表示
    除非输入具有明确的命名空间声明,否则无命名空间 哪种情况会受到尊重。

    如果html-mode = true()

    ,则属性名称是小写的

    阅读更详细的说明here

    希望这会有所帮助。

    干杯,

    Dimitre Novatchev。

答案 5 :(得分:1)

我同意克里斯·莱弗利的观点,因为HTML通常形式不是很好,你可能最适合使用正则表达式。

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

从RegExLib上的here开始

答案 6 :(得分:0)

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

另一方面,在解析html时,正则表达式非常糟糕。幸运的是,您不需要处理完整的HTML规范。您需要担心的是解析href=字符串以获取网址。即便这样也很棘手,所以我不会马上尝试。相反,我会首先提出几个问题来尝试建立一些基本规则。他们基本上都归结为“你对这份文件了解多少?”,但这里有:

  • 您知道“href”文本是否总是小写?
  • 你知道它是否总是在网址周围使用双引号,单引号或其他内容吗?
  • 它始终是有效的网址,还是您需要考虑“#”,javascript语句等内容?
  • 是否可以使用内容描述html功能的文档(IE:href=也可能在文档中而不属于锚标记)?
  • 您还可以告诉我们有关该文件的内容吗?

答案 7 :(得分:0)

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

Looking for C# HTML parser