返回

如何从嵌套和非嵌套 <a> 标签中提取所有 href 值?

php

从嵌套和非嵌套 <a> 标签中提取所有 href

问题陈述

如何有效地从 HTML 文档中提取嵌套和非嵌套 <a> 标签的所有 href 值?需要避免重复,考虑到浏览器的标签解析行为,同时捕获两种类型的 <a> 标签。

解决方案:正则表达式

我们可以使用正则表达式来实现该任务:

preg_match_all('/<a[^>]*href=["\'](.*?)["\'][^>]*>(.*?)<\/a>/s', $html, $matches);

此正则表达式模式将匹配以下内容:

  • href 属性中的 href 值(使用非贪婪匹配以避免捕获多余内容)。
  • <a> 标签内的文本(对于嵌套的 <a> 标签,这是嵌套文本)。

优点

  • 高效: 使用正则表达式比 DOM 解析更有效。
  • 准确: 考虑到浏览器的解析行为,从嵌套和非嵌套 <a> 标签中提取 href 值。
  • 去重: 避免重复的 href 值。

代码示例

$html = '<a href="example1.com">Outer Link</a>
<a href="example2.com">
    <a href="example3.com">Nested Link</a>
</a>';

preg_match_all('/<a[^>]*href=["\'](.*?)["\'][^>]*>(.*?)<\/a>/s', $html, $matches);

foreach ($matches[1] as $key => $href) {
    echo "Href: " . $href . PHP_EOL;
    echo "Text: " . $matches[2][$key] . PHP_EOL;
}

输出:

Href: example1.com
Text: Outer Link
Href: example2.com
Text: 

Href: example3.com
Text: Nested Link

常见问题解答

  1. 是否需要考虑编码?

该解决方案可以处理编码的 <a> 标签,因为它将 href 值从 HTML 实体解析为普通文本。

  1. 如何处理空文本的 <a> 标签?

空文本的 <a> 标签将被忽略,因为该模式要求 <a> 标签内至少包含一个字符。

  1. 是否可以修改该解决方案以只捕获非嵌套的 <a> 标签?

要仅捕获非嵌套的 <a> 标签,我们可以修改正则表达式模式如下:

preg_match_all('/<a[^>]*href=["\'](.*?)["\'][^>]*>(.*?)<\/a>/s', $html, $matches, PREG_SET_ORDER);

PREG_SET_ORDER 标志将确保只匹配顶级 <a> 标签。

  1. 如何处理具有相同 href 值的嵌套和非嵌套 <a> 标签?

该解决方案将优先捕获嵌套的 <a> 标签。如果存在具有相同 href 值的嵌套和非嵌套 <a> 标签,则嵌套的标签的 href 值将被捕获。

  1. 是否可以修改该解决方案以从 <a> 标签中提取其他属性?

可以通过将正则表达式模式修改为以下方式来从 <a> 标签中提取其他属性(例如,target):

preg_match_all('/<a[^>]*href=["\'](.*?)["\'][^>]*target=["\'](.*?)["\'][^>]*>(.*?)<\/a>/s', $html, $matches);