如何使用正则表达式结合preg_match从HTML字符串查找API密钥
匹配失败原因
原有正则^[a-f0-9]{32}$无法匹配到目标密钥的核心原因有两点:
- 正则中的
^和$是字符串首尾锚点,要求整个待检测字符串完全由32位小写十六进制字符组成,但你的API密钥是嵌在长HTML文本中间的片段,前后存在大量其他内容 - 示例中的API密钥前后带有空白字符,原锚点规则直接排除了“从长文本中提取子串”的匹配逻辑
实现方案
通用匹配方案(适配任意位置的32位十六进制API密钥)
调整正则去掉首尾锚点,增加单词边界避免误匹配长串中的片段,最终正则为:/\b[a-f0-9]{32}\b/i
修饰符说明:
i表示不区分大小写,可兼容密钥中出现大写A-F的场景;如果确定密钥只有小写字符,可移除该修饰符。\b为单词边界,可避免从更长的十六进制字符串中截取出32位片段造成误判。
PHP调用示例代码:
<?php // 待检测的HTML字符串 $rawHtml = '<p><code>{"page_data":"<div class=\"row\"> <div class=\"col-md-6\"> <div class=\"card\"> <div class=\"card-header\"><h5>Affiliate API<\/h5><\/div> <div class=\"card-body\" style=\"padding:0px;\"> <table class=\"table\"> <thead> <\/thead> <tbody> <tr><td>User ID<\/td> <td>372061<\/td><\/td><td><\/tr> <tr><td>MID<\/td> <td>5132<\/td><\/td><td><\/tr> <tr><td>API Key<\/td> <td id=\"api_results\"> fbb5e3abe388cab9ef652916fe124316 <\/td><td> <span class=\"badge badge-pill badge-secondary\" style=\"cursor: pointer;\" onclick=\"api_update(\'create\')\">Generate<\/span> <span class=\"badge badge-pill badge-danger\" style=\"cursor: pointer;\" onclick=\"api_update(\'disable\')\">Disable<\/span><\/td><\/tr> <tr><td>API Domain<\/td><\/tr> <\/tbody> <\/table> <\/div> <\/div> <div class=\"card\"> <div class=\"card-header\"><h5>API Guide<\/h5><\/div> <div class=\"card-body\"><\/div> <\/div> <\/div> <\/div> ","page_js_register":"function api_update(t){ if(t==\'create\'){ var r = confirm(\"Are you sure to Create New API\"); }else{ var r = confirm(\"Are you sure to Disable API\"); } if (r == true) { $.ajax({type: \"POST\", url: \"_get?type=api_update&t=\"+t, data: \'\', success: function(result){ if(result.api_key){ document.getElementById(\"api_results\").innerHTML = result.api_key; } alert_c(result.txt,result.type,\'\'); }}); } } ","title":"API"}</code></p>'; $pattern = '/\b[a-f0-9]{32}\b/'; if (preg_match($pattern, $rawHtml, $matchRes)) { $apiKey = trim($matchRes[0]); echo "检测到API密钥:" . $apiKey; // 运行输出:检测到API密钥:fbb5e3abe388cab9ef652916fe124316 } else { echo "未检测到符合规则的API密钥"; } ?>
精准定位方案(适配当前固定HTML结构,零误判)
如果待检测的HTML结构固定,API密钥始终存放在id="api_results"的td标签内,可以直接针对该位置编写匹配规则,完全避免匹配到页面中其他位置的32位十六进制字符串(比如其他MD5值、哈希串),正则如下:/id="api_results">\s*([a-f0-9]{32})\s*<\/td>/i
规则说明:
\s*用来兼容密钥前后可能存在的任意数量空白字符(空格、换行、制表符都可匹配),捕获组1会直接返回去掉前后空白的密钥内容。
PHP调用示例代码:
<?php $rawHtml = '你的待处理HTML字符串'; $pattern = '/id="api_results">\s*([a-f0-9]{32})\s*<\/td>/i'; if (preg_match($pattern, $rawHtml, $matchRes)) { $apiKey = $matchRes[1]; echo "检测到API密钥:" . $apiKey; } ?>
注意事项
- 仅当需要校验整个输入字符串是否完全为API密钥时,才使用
^和$锚点;从长文本中查找子串必须移除这两个锚点 - 匹配到结果后建议用
trim()做一次首尾空白清理,避免把格式字符带进最终获取的密钥中 - 如果页面后续结构会变化,优先选通用匹配方案;如果结构长期固定,选精准定位方案稳定性更高
内容的提问来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

