【问题标题】:Simple regex help using C# (Regex pattern included)使用 C# 的简单正则表达式帮助(包括正则表达式模式)
【发布时间】:2011-09-25 03:55:11
【问题描述】:

我有一些我正在尝试解析的网站源流。我目前的正则表达式是这样的:

Regex pattern = new Regex (
@"<a\b             # Begin start tag
    [^>]+?             # Lazily consume up to id attribute
    id\s*=\s*['""]?thread_title_([^>\s'""]+)['""]?  # $1: id
    [^>]+?             # Lazily consume up to href attribute
    href\s*=\s*['""]?([^>\s'""]+)['""]?             # $2: href
    [^>]*              # Consume up to end of open tag
    >                  # End start tag
    (.*?)                                           # $3: name
    </a\s*>            # Closing tag",
RegexOptions.Singleline | RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace );

但它不再匹配链接。我包含了一个示例字符串here

基本上我正在尝试匹配这些:

<a href="http://visitingspain.com/forum/f89/how-to-get-a-travel-visa-3046631/" id="thread_title_3046631">How to Get a Travel Visa</a>

"http://visitingspain.com/forum/f89/how-to-get-a-travel-visa-3046631/" is the **Link**
304663` is the **TopicId**
"How to Get a Travel Visa" is the **Title**

在我发布的示例中,至少有 3 个,其他的我没有计算。

我还使用RegexHero(在线免费)在将匹配项添加到代码之前以交互方式查看匹配项。

【问题讨论】:

标签: c# .net regex parsing


【解决方案1】:

为了完整起见,这里是如何使用 Html Agility Pack 完成的,这是一个强大的 .Net HTML 解析器(也可通过 NuGet 获得,因此安装大约需要 20 秒)。

加载文档、解析文档并找到 3 个链接,如下所示:

string linkIdPrefix = "thread_title_";
HtmlWeb web = new HtmlWeb();
HtmlDocument doc = web.Load("http://jsbin.com/upixof");
IEnumerable<HtmlNode> threadLinks = doc.DocumentNode.Descendants("a")
                              .Where(link => link.Id.StartsWith(linkIdPrefix));

就是这样,真的。现在您可以轻松获取数据:

foreach (var link in threadLinks)
{
    string href = link.GetAttributeValue("href", null);
    string id = link.Id.Substring(linkIdPrefix.Length); // remove "thread_title_"
    string text = link.InnerHtml; // or link.InnerText
    Console.WriteLine("{0} - {1}", id, href);
}

【讨论】:

    【解决方案2】:

    这很简单,标记改变了,现在href属性出现在id之前:

    <a\b             # Begin start tag
        [^>]+?             # Lazily consume up to href attribute
        href\s*=\s*['""]?([^>\s'""]+)['""]?             # $1: href
        [^>]+?             # Lazily consume up to id attribute
        id\s*=\s*['""]?thread_title_([^>\s'""]+)['""]?  # $2: id
        [^>]*              # Consume up to end of open tag
        >                  # End start tag
        (.*?)                                           # $3: name
        </a\s*>            # Closing tag
    

    请注意:

    • 这主要是为什么这是一个坏主意。
    • 组号已更改。您可以改用命名组:(?&lt;ID&gt;[^&gt;\s'""]+) 而不是 ([^&gt;\s'""]+)
    • 引号仍然被转义(这在字符集中应该没问题)

    regex hero 上的示例。

    【讨论】:

    • 谢谢,在您的示例链接中,是否已修改?当我打开它时,它显示 0 个匹配项。
    • @JoanVenge - 这很奇怪......我就这样吧,它已经让我失望了,但我认为这个想法很清楚:)谢谢!
    • Regex Hero 会在使用永久链接功能时截断超过 4,000 个字符的目标字符串。我突然想到我可能应该提高限制。 @Joan - 如果您复制并粘贴原始 html,那么 Kobi 的正则表达式应该可以工作。
    • 我将限制提高到 500,000 个字符。所以这应该工作......regexhero.net/tester/?id=2509fab5-243f-4fa3-aeb2-61658ae38f7b
    • @Joan 和 Kobi - 不客气。在场景中使用 HTML Agility Pack 是绝对正确的。这也是我会做的。顺便说一句,我正在开发一个名为 XML Hero 的新工具,它将帮助解决此类问题。
    【解决方案3】:

    Don't do that(好吧,almost,但并不适合所有人)。 Parsers 是针对这种类型的。

    【讨论】:

    • 谢谢,但我需要一个快速修复,而不是大的改变。此外,它是一种个人工具,无论如何都没有人使用。此外,我在生产代码中看到了许多类似做法的实例,所以我认为即使是大多数程序员也没有遵循这些好的做法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-16
    相关资源
    最近更新 更多