strip_tags()不能直接截取,必须先清洗再截取:解码HTML实体→剥离标签→合并空白→按字符截取;否则标签长度计入、截断异常或解析错误。

strip_tags() 是最直接的解法,但“提取摘要”不是简单删标签就能完事——它本质是「清洗 + 截取」两个动作,且顺序错不得。
为什么不能只用 strip_tags() 直接截取?
常见错误是先 mb_substr() 再 strip_tags(),比如:$summary = mb_substr(strip_tags($html), 0, 100, 'utf-8');
这会导致:原始 HTML 中的标签长度被算进 100 字符里(如 <p> 占 4 字符),实际纯文本远少于预期;更糟的是,若截断点落在标签中间(如 <div>Hello<str...),strip_tags() 可能漏掉后续内容或产生解析异常。
必须先清洗,再截取
正确流程只有这一种:
→ 解码 HTML 实体(防止 变成乱码)
→ 剥离所有标签
→ 合并多余空白(连续空格、换行、制表符)
→ 最后按字符数截取
-
$clean = htmlspecialchars_decode($html, ENT_QUOTES | ENT_HTML5);—— 必须加ENT_HTML5,否则某些实体(如')不识别 -
$clean = strip_tags($clean);—— 安全起见,不要传第二个参数(即不限定保留标签),摘要不需要格式 -
$clean = preg_replace('/\s+/', ' ', $clean);—— 用单个空格替代所有空白符,比逐个str_replace()更可靠 -
$summary = mb_substr(trim($clean), 0, 120, 'utf-8');——trim()放最后,避免开头结尾残留空格影响长度计算
preg_replace() 手动去标签的风险在哪?
有人写 preg_replace('/]*>/', '', $html) 试图替代 strip_tags(),这在以下场景会翻车:
- 遇到含
>的合法文本(如数学公式x > y或 JS 字符串"a > b"),正则会提前终止匹配,把后面内容当标签删掉 - 标签属性含未闭合引号(如
<img src="https://img.php.cn/upload/article/001/503/042/178316146826151.jpg" alt="php正则表达式提取文章摘要怎么过滤标签保留文字" />),正则无法识别,可能吞掉大段正文</li> <li>自闭合标签(<code><br/>
、<hr>)和 HTML5 新标签(<article></article>)兼容性差,strip_tags()内部用词法分析,更鲁棒
中文摘要要特别注意编码和截断边界
PHP 的 mb_substr() 在 UTF-8 下对汉字安全,但前提是输入字符串本身是 UTF-8 编码。如果来源是 GBK 或其他编码,mb_substr() 会截断字节导致乱码。此时必须先转换:
- 确认源数据编码:用
mb_detect_encoding($html, ['UTF-8', 'GBK', 'BIG5'], true)检测(注意第三个参数true表示 strict) - 强制转 UTF-8:
$html = mb_convert_encoding($html, 'UTF-8', $detected_encoding); - 截取时永远显式指定
'utf-8',别依赖默认值
真正容易被忽略的是:摘要末尾不该出现半截词或孤立标点。但 PHP 没有开箱即用的「语义截断」能力,mb_substr() 只认字节/字符位置——这意味着你得自己加逻辑判断是否在标点后截断,或者接受「宁可少几个字,也不能割裂句子」的妥协。



















