资讯文章 资讯 · NEWS
搜索结果里那段摘要怎么来的:目录站的片段生成和关键词高亮
2026-10-24 约 1,803 字 预计阅读 5 分钟 yiyunkj
搜
站内搜索的结果列表,用户扫的就是两样东西:标题和下面那段摘要。摘要做好了,用户一眼能判断要不要点;做不好,整页看起来像一堆重复内容。
目录站的条目简介通常不长,而且相当一部分是模板生成的,直接截前 80 个字会得到一批高度相似的结果。这是最常见的源头问题。

图片来源:网络,版权归原作者所有,侵权请联系删除
三种截取策略
| 策略 | 做法 | 适合 | 问题 |
|---|---|---|---|
| 固定前 N 字 | 从开头截 | 简介质量高且各异 | 模板简介会整页雷同 |
| 以查询词为中心 | 找到词的位置,前后各取一段 | 简介较长 | 词没命中时要有兜底 |
| 字段拼接 | 分类 + 标签 + 特点拼一句 | 结构化字段丰富的条目 | 需要维护拼接模板 |
实际用得最多的是「以查询词为中心,取不到就退到固定前 N 字」的组合。
截取时要注意别切在半句话中间。做法是截完之后回退到最近的句末标点,找不到标点再按字数硬截。中文里句号、问号、感叹号、分号都算断句点,另外要处理英文句点后面跟空格的情况,不然会把域名和小数点当成句子结束。
高亮的两个安全问题
必须先转义再插入标签
这是最容易出事的地方。原始文本来自条目简介,其中可能包含 HTML;查询词来自用户输入,可能包含任何字符。如果先把高亮标签插进去再转义,标签本身会被转义掉,高亮失效;如果不转义直接输出,就是存储型 XSS 的入口。
正确顺序是:先对原文做 HTML 转义,再在转义后的文本上做高亮替换。这样查询词里的尖括号也已经被转义,插进去的标签是唯一的可信 HTML。
import re, html
def highlight(text, query):
safe = html.escape(text) # 第一步:转义原文
q = html.escape(query) # 查询词同样要转义
if not q:
return safe
pat = re.compile(re.escape(q), re.I)
return pat.sub(lambda m: f"<mark>{m.group(0)}</mark>", safe)
多词查询要拆开处理
用户输入「设计 素材」这类多词查询,逐个词替换要小心顺序——先替换短词会破坏长词的匹配。做法是按词长降序处理,或者一次性构造包含所有词的正则。
另外,如果站点做了分词和同义词扩展,高亮应该基于「实际参与匹配的词形」,而不是用户原始输入。搜「网站设计」通过同义词命中了「网页设计」,高亮「网站」和「设计」会让用户困惑,不如高亮实际命中的那个词。
别用 innerHTML 拼
前端拿到数据后高亮,常见的写法是拼字符串塞进 innerHTML,这条路同样有 XSS 风险。更稳的做法是后端返回已经处理好、且转义过的片段,前端直接渲染;或者前端用 DOM API 构造文本节点和 mark 元素,不碰 innerHTML。
mark 元素本身语义是对的,屏幕阅读器能识别。如果担心样式,用 CSS 控制,别用 span 加内联样式凑。
它和 meta description 是两回事
经常有人把这两个混起来。区别很明确。
- meta description:给搜索引擎看的,写在页面 head 里,一个页面只有一份,内容是稳定的。
- 搜索结果摘要:给自己站内搜索结果页看的,同一条条目在不同查询词下摘要可以不同,是动态生成的。
两者都不直接影响排名,但作用路径不同:前者影响搜索结果里的点击率,后者影响站内搜索的转化。
还有第三个容易混的:搜索引擎结果里的摘要。那段文字由搜索引擎自己从页面内容里挑,不完全听 meta description。有 nosnippet、max-snippet、data-nosnippet 这几个手段可以控制,但那是另一套机制。
零结果和弱结果的摘要
搜索没有结果时,摘要这块就没得做了,重点是兜底内容:推荐相近分类、给出拼写建议、说明为什么没找到。这部分用户的耐心只有几秒。
更要留意的是「弱结果」——技术上返回结果了,但每条摘要都是同一句模板话。这种情况用户的感受比零结果更差,因为看起来像系统在敷衍。判断标准是:把查询词盖住,看这一页的摘要还有没有区别。没区别就说明简介数据源有问题,得回去改简介生成逻辑,不是在摘要这层能修好的。
几条实操建议
摘要长度控制在 80 到 120 字,移动端一行放不下就两行,别超过三行。太长会挤掉结果条数。
高亮次数限制在三次以内。满屏高亮的视觉噪音比不高亮还糟。
摘要里带一点结构化信息比纯文字有用。比如把分类名和「已核对」的时间放在摘要末尾,用户不用点进去就能判断时效性。
搜索结果页本身保持 noindex。它不该进索引,也不该出现在 sitemap 里。