正确做法是直接从原始来源(如textarea.value、富文本API、data-属性)获取纯文本,避免用innerHTML赋值再读取;DOM处理应cloneNode+normalize+textContent;Python用BeautifulSoup需设get_text(separator=' ', strip=True)等合理参数。

用 textContent 读取,别碰 innerHTML
直接赋值 innerHTML 再读回来,空格早被浏览器吃掉了——HTML 规范要求连续空白(空格、制表、换行)压缩成单个空格,首尾全丢。你拼了十个空格,渲染出来还是一个。
正确做法是:从原始来源(比如 textarea.value、富文本编辑器的 API、data- 属性)直接取 textContent 或等价纯文本接口:
-
quill.getContents().ops→ 转 Delta →Delta.insert()提取带换行逻辑的纯文本 -
editor.getContent({ format: 'text' })(TinyMCE) - 原生
contenteditable元素:先cloneNode(true),再normalize(),最后取textContent—— 注意:normalize()必须在节点对象上调用,对字符串调用无效
get_text(separator=' ', strip=True) 是 BeautifulSoup 的标准解法
Python 侧提取混乱,大概率是没设好 get_text 参数。默认行为会把块级标签间的换行原样保留,导致输出里一堆 \n\n;不设 strip 则每段首尾带着缩进和回车。
推荐组合:
立即学习“前端免费学习笔记(深入)”;
-
element.get_text(separator=' ', strip=True):最通用,空格分隔 + 清首尾,适合段落合并 -
element.get_text(separator='\n', strip=True):想保留段落结构但去掉多余空行,就用换行符分隔 - 避免
separator=''(空字符串),那会把所有文本粘连,比如<p>A</p><div class="aritcle_card flexRow"> <div class="artcardd flexRow"> <a class="aritcle_card_img" href="/xiazai/skill10246" title="HTML Text Extract"><img src="https://img.php.cn/upload/skill/001/246/273/6adaf20dee630206.jpg" alt="HTML Text Extract" ></a> <div class="aritcle_card_info flexColumn"> <a href="/xiazai/skill10246" title="HTML Text Extract">HTML Text Extract</a> <p>从HTML页面(URL、文件或标准输入)中提取主体内容文本,去除导航、页脚、广告和模板文本。可直接传递给readability_check或其他文本工具。</p> </div> <a href="/xiazai/skill10246" title="HTML Text Extract" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span> </a> </div> </div> <p>B</p>变成"AB"
DOM 树遍历清理:只动文本节点,不动结构
如果必须处理已有 DOM 元素(比如服务端返回了一段带冗余缩进的 HTML 字符串),不能靠正则全局替换——它会误杀标签内属性值或实体编码(如 )。
安全做法是用原生 DOM 遍历,逐个处理文本节点:
- 递归访问
childNodes,只对nodeType === Node.TEXT_NODE操作 - 用
/\S/.test(text)过滤掉纯空白节点(比如只有换行缩进的<div>\n \t</div>) - 对有效文本调用
text.trim().replace(/\s+/g, ' '):既去首尾,又把中间多个空白(含制表、全角空格)压成单空格 - 全程改
textContent,不碰innerHTML,结构、事件、属性全保留
后端传纯文本比前端硬清洗更可靠
如果后端能改,优先让 API 返回 plain_text 字段,而不是 html_content。前端拿到后用 white-space: pre-wrap 包裹渲染——这比在 HTML 字符串里跟各种 、、零宽字符死磕强得多。
富文本导出时容易混入 Unicode 控制符(如 \u200B 到 \u200F、\uFEFF),strip_tags() 类函数默认不处理它们。真要走 PHP 后端清洗,得显式补上这些范围:preg_replace('/[\s\x{200B}-\x{200F}\x{FEFF}]+/u', ' ', $text)。
复杂点在于:空格问题从来不是孤立的,它总和富文本编辑器行为、后端存储格式、CSS 渲染策略耦合在一起。单独修一处,往往另一处又冒出来。


















