c# - 解析 HTML 文档 : Regular expression or LINQ?

标签 c# regex linq parsing linq-to-xml

尝试解析 HTML 文档并提取一些元素(任何指向文本文件的链接)。

当前的策略是将 HTML 文档加载到字符串中。然后找到文本文件链接的所有实例。它可以是任何文件类型,但是对于这个问题,它是一个文本文件。

最终目标是拥有一个 IEnumerable 字符串对象列表。这部分很简单,但解析数据才是问题。

<html>
<head><title>Blah</title>
</head>
<body>
<br/>
<div>Here is your first text file: <a href="http://myServer.com/blah.txt"></div>
<span>Here is your second text file: <a href="http://myServer.com/blarg2.txt"></span>
<div>Here is your third text file: <a href="http://myServer.com/bat.txt"></div>
<div>Here is your fourth text file: <a href="http://myServer.com/somefile.txt"></div>
<div>Thanks for visiting!</div>
</body>
</html>

最初的方法是:

  • 将字符串加载到 XML 文档中,并以 Linq-To-Xml 方式对其进行攻击。
  • 创建一个正则表达式,以查找以 href= 开头并以 .txt 结尾的字符串>

问题是:

  • 那个正则表达式会是什么样子?我是正则表达式新手,这是我正则表达式学习的一部分。
  • 您会使用哪种方法来提取标签列表?
  • 哪种方式效率最高?
  • 哪种方法最具可读性/可维护性?


更新: 感谢Matthew关于 HTML Agility Pack 建议。它工作得很好! XPath 建议也适用。我希望我可以将两个答案都标记为“答案”,但我显然不能。它们都是问题的有效解决方案。

这是一个使用 Jeff 建议的正则表达式的 C# 控制台应用程序.它可以很好地读取字符串,并且不会包含任何未以 .txt 结尾的 href。对于给定的示例,它正确地不在结果中包含 .txt.snarg 文件(如 HTML 字符串函数中提供的那样)。

using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using System.IO;

namespace ParsePageLinks
{
    class Program
    {
        static void Main(string[] args)
        {
            GetAllLinksFromStringByRegex();
        }

        static List<string> GetAllLinksFromStringByRegex()
        {
            string myHtmlString = BuildHtmlString();
            string txtFileExp = "href=\"([^\\\"]*\\.txt)\"";

            List<string> foundTextFiles = new List<string>();

            MatchCollection textFileLinkMatches = Regex.Matches(myHtmlString, txtFileExp, RegexOptions.IgnoreCase);
            foreach (Match m in textFileLinkMatches)
            {
                foundTextFiles.Add( m.Groups[1].ToString()); // this is your captured group
            }

            return files;
        }

            static string BuildHtmlString()
            {
                return new StringReader(@"<html><head><title>Blah</title></head><body><br/>
<div>Here is your first text file: <a href=""http://myServer.com/blah.txt""></div>
<span>Here is your second text file: <a href=""http://myServer.com/blarg2.txt""></span>
<div>Here is your third text file: <a href=""http://myServer.com/bat.txt.snarg""></div>
<div>Here is your fourth text file: <a href=""http://myServer.com/somefile.txt""></div>
<div>Thanks for visiting!</div></body></html>").ReadToEnd();
            }       
        }
    }

最佳答案

都没有。将其加载到 (X/HT)MLDocument 中并使用 XPath,这是一种处理 XML 的标准方法,非常强大。要查看的函数是 SelectNodesSelectSingleNode .

因为您显然使用的是 HTML(不是 XHTML),所以您应该使用 HTML Agility Pack .大多数方法和属性与相关的 XML 类匹配。

使用 XPath 的示例实现:

    HtmlDocument doc = new HtmlDocument();
    doc.Load(new StringReader(@"<html>
<head><title>Blah</title>
</head>
<body>
<br/>
<div>Here is your first text file: <a href=""http://myServer.com/blah.txt""></div>
<span>Here is your second text file: <a href=""http://myServer.com/blarg2.txt""></span>
<div>Here is your third text file: <a href=""http://myServer.com/bat.txt""></div>
<div>Here is your fourth text file: <a href=""http://myServer.com/somefile.txt""></div>
<div>Thanks for visiting!</div>
</body>
</html>"));
        HtmlNode root = doc.DocumentNode;
        // 3 = ".txt".Length - 1.  See http://stackoverflow.com/questions/402211/how-to-use-xpath-function-in-a-xpathexpression-instance-programatically
        HtmlNodeCollection links = root.SelectNodes("//a[@href['.txt' = substring(., string-length(.)- 3)]]");
    IList<string> fileStrings;
    if(links != null)
    {
        fileStrings = new List<string>(links.Count);
        foreach(HtmlNode link in links)
        fileStrings.Add(link.GetAttributeValue("href", null));
    }
    else
        fileStrings = new List<string>(0);

关于c# - 解析 HTML 文档 : Regular expression or LINQ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/907563/

相关文章:

java - 在 Struts2 中使用 RegexFieldValidator 时,消息参数不会替换为存储在属性文件中的消息中的实际占位符

python - SQLAlchemy + PostgreSQL + PG 正则表达式

regex - 日志文件的有效 grep

c# - 使用没有外部变量的 LINQ 连接字典(值)中的所有字符串

c# - IQueryable 和计数

c# - 使用正则表达式获取指数值

c# - 用正则表达式替换字符串

c# - DataTable.Rows.InsertAt 不会接受 DataTable.Rows.Add 接受的新对象 []

linq - 在 Entity Framework 中的运算符中实现

C# 字典 : Multiple KEYS per Value