HtmlDiff 仅支持行级对比,需将文本用 splitlines(keepends=True) 转为行列表;单词级差异须用 SequenceMatcher 获取 opcodes,并自行渲染 HTML;预处理(清理空格、统一编码、处理标点)和 UTF-8 编码写入是避免乱码与误判的关键。

用 difflib.HtmlDiff 生成带颜色标记的HTML对比页
直接调用 HtmlDiff 是最快出 HTML 报告的方式,但它默认按行比较,且对空格和换行敏感。如果两段文本是自然语言(比如用户提交的修改稿),需先按行切分并清理首尾空白。
常见错误现象:make_file() 返回空字符串或只显示“no difference”,往往是因为输入是单个长字符串没分行,或前后有不可见字符(如 \r\n 和 \n 混用)。
- 把文本用
.splitlines(keepends=True)切成行列表,保留换行符,避免因换行差异被误判为整行不同 - 传入
HtmlDiff().make_file()时,两个参数必须是list[str],不能是str - 可选传
fromdesc和todesc参数标注左右标题,否则默认显示 “from” / “to” - 若想高亮单词级差异(比如同一行内只有几个字变了),
HtmlDiff做不到——它只支持行级,得换思路
用 difflib.SequenceMatcher 获取细粒度差异位置
当需要知道「哪几个字符被插入/删除/替换」,或者想自己渲染 HTML(比如加 tooltip、折叠长段落),就得用 SequenceMatcher。它不生成 HTML,但能返回操作码列表(opcodes),描述从 A 到 B 的最小编辑步骤。
使用场景:做代码 diff 工具、文档修订追踪、或集成进 Web 页面做动态高亮。
立即学习“Python免费学习笔记(深入)”;
-
SequenceMatcher(a=text1, b=text2).get_opcodes()返回形如[('equal', 0, 3, 0, 3), ('replace', 3, 5, 3, 6)]的列表,每个元组含义是(tag, i1, i2, j1, j2),对应 A[i1:i2] → B[j1:j2] - tag 可能是
'equal'、'delete'、'insert'、'replace';注意'replace'实际是 delete + insert 组合,不是原地修改 - 若文本含大量 Unicode 或 emoji,确保两端都用相同编码(推荐统一用
str,别混用bytes),否则get_opcodes()可能错位 - 性能影响:对超长文本(>10 万字符),
SequenceMatcher时间复杂度接近 O(n²),建议先按段落切分再逐段比
处理中文、空格与标点导致的误差
difflib 默认把所有字符(包括空格、制表符、全角/半角标点)视为独立 token,所以两段文字仅因「,」和「,」(全角逗号)不同,就会标为整块差异。这不是 bug,是设计如此。
容易踩的坑:用户说“内容明明一样,为什么标红一大片”,大概率是编码、空格、换行符或中英文标点混用。
- 预处理建议:用
.replace(' ', '').replace('\t', '').replace('\u3000', '')清理全半角空格;用正则re.sub(r'[,。!?;:""''()【】《》]', lambda m: m.group(0)[0], text)统一中文标点(慎用,可能破坏语义) - 更稳妥的做法是自定义
isjunk函数传给SequenceMatcher,例如lambda x: x in ' \t\n'让空格被视为可忽略 junk,但注意这会降低对缩进变更的识别能力 - 中文分词后比对(如用
jieba)效果更好,但已超出difflib范围,属于业务层适配
保存 HTML 文件时的编码与浏览器兼容问题
生成的 HTML 字符串默认是 str,写入文件时若不指定 encoding,Windows 上可能用 gbk 导致中文乱码,浏览器打不开。
性能 / 兼容性影响:部分老浏览器(IE11)不支持 <ins>/<del> 标签的 CSS 样式,需额外加 class 并用内联 style 控制颜色。
- 写文件务必用
open(... , encoding='utf-8'),并在 HTML 字符串开头加上<meta charset="utf-8"> -
HtmlDiff输出的 HTML 不含 CSS,浏览器默认样式较丑;可手动在<head>中注入 style,例如给<ins>加background:#d4fcbc - 如果 HTML 要嵌入现有页面,注意
HtmlDiff生成的是完整 HTML 文档(含<html>标签),需提取<body>内容或改用make_table()只输出表格片段
HtmlDiff 快但糙,SequenceMatcher 精确但要自己画 HTML。最常被忽略的是预处理——尤其当文本来自富文本编辑器、Word 导出或 OCR 结果时,隐藏字符和格式残留几乎必然存在。



















