从HTML内容中获取href和src的正则表达式?

5

我在尝试从HTML字符串中提取href和src链接。根据这篇帖子,我已经成功获取了图片部分。请问有人能帮忙调整正则表达式使其也可以将href URL放入集合中吗?

public List<string> GetLinksFromHtml(string content)
{
    string regex = @"<img[^>]*?src\s*=\s*[""']?([^'"" >]+?)[ '""][^>]*?>";
    var matches = Regex.Matches(content, regex, RegexOptions.IgnoreCase | RegexOptions.Singleline);
    var links = new List<string>();

    foreach (Match item in matches)
    {
        string link = item.Groups[1].Value;
        links.Add(link);
    }

    return links;
}

为什么不直接使用常规的 HTML解析器 呢? - Roman
1
我不想部署额外的库。它应该是一种轻便快捷的方法,我可以轻松地将其添加到任何项目中。 - TruMan1
7
你应该考虑使用一个库。如果只是一次性的hack,正则表达式和HTML可能可行,但如果你会经常使用它,有一天你会尝试解析带有恶意注释和嵌入式JavaScript的HTML,那么一切都会崩溃。 - Jens
1
正则表达式并不适合用于解析复杂的HTML。但是,如果您能够100%保证将要解析的标签是您自己编写的,并且完全符合图像标记的规范,您也许可以使用它。不过,HtmlAgilityPack是更完美的解决方案。 - Mike B
5个回答

11

好了,没有“额外的库”,而且“快速轻便”,这里给你:

<(?<Tag_Name>(a)|img)\b[^>]*?\b(?<URL_Type>(?(1)href|src))\s*=\s*(?:"(?<URL>(?:\\"|[^"])*)"|'(?<URL>(?:\\'|[^'])*)')

或作为 C# 字符串:

@"<(?<Tag_Name>(a)|img)\b[^>]*?\b(?<URL_Type>(?(1)href|src))\s*=\s*(?:""(?<URL>(?:\\""|[^""])*)""|'(?<URL>(?:\\'|[^'])*)')"

这段代码将标签名(aimg)捕获到"Tag_Name"组,URL类型(hrefsrc)捕获到"URL_Type"组,URL捕获到"URL"组(我知道,我在命名组时有点创意)。

它处理任意类型的引号("'),即使在URL中的任何引号都应该已经被编码为实体,但它将忽略任何单个转义的引号字符\'\"

它不会忽略未关闭的标签(因此是格式不正确的HTML),它会查找其中一个标签的开头,例如<aimg,然后继续忽略除大于号(>)之外的所有内容,直到找到匹配的URL类型属性(a标签的hrefimg标签的src),然后匹配其内容。然后它退出并不再关心标签的其余部分!

如果您想对此进行详细解释,请告诉我,但是这里是它在这个页面上产生的匹配示例:

<Match>                                  'Tag' 'URL_Type' 'URL'
---------------------------------------- ----- ---------- -----------------------------
<a href="http://meta.stackoverflow.com"   a     href      http://meta.stackoverflow.com
<a href="/about"                          a     href      /about
<a href="/faq"                            a     href      /faq
<a href="/"                               a     href      /
<a id="nav-questions" href="/questions"   a     href      /questions
...
<img src="/posts/8066248/ivc/d499"        img   src       /posts/8066248/ivc/d499

它找到了总共 140 个标签(我假设其他发布者会稍微增加这个数字)


0
以下代码可以帮助您获取HTML中的每个链接,获取它们后,您可以获取链接中更多详细的元素:
string html = "123<a href=\"http://www.codeios.com/home.php\">123123</a>789";
Regex r = new Regex(@"<a.*?href=(""|')(?<href>.*?)(""|').*?>(?<value>.*?)</a>");

foreach (Match match in r.Matches(html))
{
    string url = match.Groups["href"].Value;
    string text = match.Groups["value"].Value;

    Response.Write(url + text);
}

0

太可怕了!因为使用正则表达式解析HTML是邪恶的

 <img[^>]*?src\s*=\s*[""']?([^'"" >]+?)[ '""][^>]*?href\s*=\s*[""']?([^'"" >]+?)[ '""][^>]*?>

在使用正则表达式解析 SGML 时,唯一的危险是如果您尝试解析嵌套在其他 SGML 中的 SGML - 如果没有必要承认嵌套(比如在 HTML 中的图像和锚标签中?),那么就没有问题! - Code Jockey

0

我刚刚草拟了这个正则表达式,但已经测试并且可用,请告诉我是否符合您的需求。(url和img都是命名组,因此很容易检索)

<a(.*?)href="(?P<url>.*?)"(.*?)><img(.*)src="(?P<img>.*?)"(.*?)></a>

你也可以通过在 <a></a> 标签中添加问号符号来捕获没有链接的图像,如下所示:

(<a(.*?)href="(?P<url>.*?)"(.*?)>)?(<img(.*)src="(?P<img>.*?)"(.*?)>)(</a>)?

Shai


那样做不太行,HTML允许属性使用单引号或双引号。 - Roman
设置其中任何一个都不麻烦的,使用('|") :) 我非常不推荐在HTML解析中使用正则表达式,但他要求一个特定的解决方案,我尽力提供了。 - Shai Mishali
这是针对 .Net 的,我相信 - 据我所知,.Net 不支持 (?P<xxxx>...) 组命名结构 - 他们改变了吗?还是我一直错了? - Code Jockey
我不是来自.NET世界 :) 我只是尝试了一下正则表达式。他只需要更改. 我在这里看到有人使用(?<>)语法,所以在那种情况下,只需删除P即可完成工作。 - Shai Mishali
2
@CodeJockey:.NET正则表达式支持命名捕获组。语法也几乎正确,只需要去掉P即可。 - Roman
@R0MANARMY 我认为这可能是我上面评论措辞不当的问题。是的 - .Net支持它们 - 只是不支持(?P<xxxx>...)风格(特别是 - 如您所指出的 - 构造中的P部分)。相反,它识别形式(?<xxx>...)(如我的答案中所使用的)以及(?'xxx'...),在我看来这种形式非典型、非“标准”,更加令人困惑,因为在复杂表达式中更难阅读。因此,应该将其烧毁(叹气...如果这只是可能的话)。尽管如此,它仍然能够识别它! - Code Jockey

-1

链接和图片可以在多个位置找到。

-Link
    -href
        (?<AttributeName>(?:href))\s*=\s*["'](?<AttributeValue>(?:[^"'])*)
        for c# = (?<AttributeName>(?:href))\s*=\s*[""'](?<AttributeValue>(?:[^""'])*)

点击此处查看

-Image
    -Image_DirectSource
        -src
        -background
            (?<AttributeName>(?:src|background))\s*=\s*["'](?<AttributeValue>(?:[^"'])*)
            for c# = (?<AttributeName>(?:src|background))\s*=\s*[""'](?<AttributeValue>(?:[^""'])*)

点击此处查看

    _Image_IndirectSource   
        -style
            -background:url()
            background\s*:\s*url\s*\(\s*(?<AttributeValue>(?:[^)])*)

点击此处查看


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接