
本文介绍使用 PHP 将 HTML 格式的邮箱链接按域名后缀(如 gmail.com、yahoo.com)分组,再将同后缀的邮箱用竖线 | 连接并分行输出的完整实现方案。
本文介绍使用 php 将 html 格式的邮箱链接按域名后缀(如 gmail.com、yahoo.com)分组,再将同后缀的邮箱用竖线 `|` 连接并分行输出的完整实现方案。
在网页抓取或邮件列表处理场景中,常需对嵌入 HTML 标签的邮箱地址进行结构化整理。核心目标是:按邮箱域名后缀(即 @ 后的部分)分组 → 同组邮箱横向合并 → 每组独占一行。直接反转字符串再排序(如原思路中用 strrev())不仅低效,且无法准确提取后缀,易受 HTML 属性干扰。
正确做法是:先解析邮箱文本内容,提取域名后缀作为分组键,再利用关联数组聚合,最后有序拼接输出。以下是推荐的健壮实现:
<?php $emails = [
'<a class="__cf_email__" data-cfemail="8afbfdefcaf3ebe2e5e5a4e9e5e7" href="/cdn-cgi/l/email-protection">[email protected]',
'<a class="__cf_email__" data-cfemail="7903011a391e14181015571a1614" href="/cdn-cgi/l/email-protection">[email protected]</a>',
'<a class="__cf_email__" data-cfemail="65060100250d0a1108040c094b060a08" href="/cdn-cgi/l/email-protection">[email protected]</a>',
'<a class="__cf_email__" data-cfemail="ef8e8d8caf88828e8683c18c8082" href="/cdn-cgi/l/email-protection">[email protected]</a>',
'<a class="__cf_email__" data-cfemail="6307060523040e020a0f4d000c0e" href="/cdn-cgi/l/email-protection">[email protected]</a>',
'<a class="__cf_email__" data-cfemail="91a0a3a2d1f9fee5fcf0f8fdbff2fefc" href="/cdn-cgi/l/email-protection">[email protected]</a>',
];
// 步骤1:按域名后缀分组(使用正则更鲁棒,但简单场景可用 explode)
$emailGroups = [];
foreach ($emails as $email) {
// 安全提取邮箱文本:匹配 [email protected] 格式(兼容 Cloudflare 邮箱保护)
if (preg_match('/\[email\s*protected\]/i', $email)) {
// 若需兼容真实邮箱(非占位符),建议先解码 data-cfemail 或使用 DOM 解析
// 此处假设占位符统一,仅按 @ 分割提取后缀
$parts = explode('@', $email);
if (isset($parts[1])) {
// 提取后缀(去除闭合标签及后续字符)
$domainPart = $parts[1];
$suffix = strtok($domainPart, ''); // 截断 HTML 标签
$suffix = trim($suffix);
if (!empty($suffix)) {
$emailGroups[$suffix][] = $email;
}
}
}
}
// 步骤2:按键(域名后缀)升序排序
ksort($emailGroups);
// 步骤3:对每组内邮箱按原始顺序或内容排序(可选),再用 '|' 连接
$resultLines = [];
foreach ($emailGroups as $domain => $group) {
// 可选:组内按邮箱字符串排序(确保稳定输出)
usort($group, function($a, $b) {
return strcmp($a, $b);
});
$resultLines[] = implode('|', $group);
}
// 输出结果(每组一行)
foreach ($resultLines as $line) {
echo $line . "\n";
}
?>
✅ 关键说明与注意事项:
- 避免依赖 explode('@') 直接解析 HTML:若邮箱嵌套在复杂结构中,应优先使用 DOMDocument 或正则 preg_match('/[a-z0-9._%+-]+@([a-z0-9.-]+\.[a-z]{2,})/i', $html, $matches) 提取真实域名;
- Cloudflare 邮箱保护处理:data-cfemail 是编码值,若需还原真实邮箱,须实现解码逻辑(不在本例范围,但生产环境务必考虑);
- 空值与异常防御:代码中已加入 isset() 和 !empty() 判断,防止因格式异常导致 Notice 错误;
- 性能提示:对于海量数据,可改用 array_reduce() 或生成器优化内存占用。
最终输出严格遵循需求:相同后缀邮箱位于同一行,以 | 分隔,且所有分组按字母序排列,清晰、可维护、可扩展。











