利用 PHP 正则表达式从 HTML 中提取关键数据

利用 PHP 正则表达式从 HTML 中提取关键数据
最新回答
屋顶上的小猫咪

2021-10-20 19:33:18

在 PHP 中,使用正则表达式从 HTML 中提取关键数据(如标题、链接、电子邮件地址和电话号码)是一种常见需求。以下是具体实现方法和注意事项:

1. 提取标题

正则表达式:/<title>(.*?)</title>/代码示例

$html = "<html><head><title>我的标题</title></head><body></body></html>";preg_match_all("/<title>(.*?)</title>/", $html, $matches);echo $matches[1][0]; // 输出:我的标题

关键点

  • 使用非贪婪匹配 .*? 避免匹配到多余的闭合标签。
2. 提取链接

正则表达式:/<as+href="([^"]+)"[^>]*>(.*?)</a>/代码示例

$html = '<a href="
https://example.com">
示例链接</a>';preg_match_all("/<as+href="([^"]+)"[^>]*>(.*?)</a>/", $html, $matches);print_r($matches[1]); // 输出链接数组print_r($matches[2]); // 输出链接文本数组

关键点

  • 匹配 href 属性值([^"]+ 表示非引号字符)。
  • 允许链接标签有其他属性(如 class、target),通过 [^>]* 跳过。
3. 提取电子邮件地址

正则表达式:/[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+.[a-zA-Z]{2,}/代码示例

$html = "联系我:user@example.com 或 support@domain.org";preg_match_all("/[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+.[a-zA-Z]{2,}/", $html, $matches);print_r($matches[0]); // 输出所有匹配的邮箱

关键点

  • 匹配常见邮箱格式,但可能漏掉特殊字符(如 + 在部分邮箱中允许)。
4. 提取电话号码

正则表达式:/(?d{3})?[-s]?d{3}[-s]?d{4}/代码示例

$html = "电话:(123) 456-7890 或 987-654-3210";preg_match_all("/(?d{3})?[-s]?d{3}[-s]?d{4}/", $html, $matches);print_r($matches[0]); // 输出所有匹配的电话号码

关键点

  • 支持格式:(123) 456-7890、123-456-7890、123 456 7890。
注意事项
  1. 正则表达式的局限性

    HTML 结构复杂时(如嵌套标签、属性含特殊字符),正则表达式可能失效。建议使用 DOM 解析器(如 DOMDocument)处理复杂 HTML。

  2. 性能优化

    对大文本多次使用 preg_match_all 可能影响性能,可考虑预编译正则(preg_quote)或限制匹配范围。

  3. 转义特殊字符

    在动态生成正则时,用 preg_quote 转义用户输入,避免正则注入。

完整示例代码$html = <<<HTML<html><head><title>测试页面</title></head><body> <a href="
https://example.com">
示例</a> <p>邮箱:test@example.com</p> <p>电话:123-456-7890</p></body></html>HTML;// 提取标题preg_match_all("/<title>(.*?)</title>/", $html, $titleMatches);echo "标题: " . $titleMatches[1][0] . "n";// 提取链接preg_match_all("/<as+href="([^"]+)"[^>]*>(.*?)</a>/", $html, $linkMatches);echo "链接: " . $linkMatches[1][0] . "n";// 提取邮箱preg_match_all("/[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+.[a-zA-Z]{2,}/", $html, $emailMatches);echo "邮箱: " . $emailMatches[0][0] . "n";// 提取电话preg_match_all("/(?d{3})?[-s]?d{3}[-s]?d{4}/", $html, $phoneMatches);echo "电话: " . $phoneMatches[0][0] . "n";替代方案:使用 DOM 解析器

若 HTML 结构复杂,推荐以下方法:

$dom = new DOMDocument();@$dom->loadHTML($html); // 抑制加载错误// 提取标题$title = $dom->getElementsByTagName('title')->item(0)->nodeValue;// 提取链接$links = [];foreach ($dom->getElementsByTagName('a') as $link) { $links[] = $link->getAttribute('href');}

通过正则表达式或 DOM 解析器,可以灵活应对不同场景的数据提取需求。正则适合简单模式,而 DOM 解析器更适合复杂 HTML 结构。