--- title: "06-html_to_text" created: 2026-04-02 tags: - 项目 aliases: - html_to_text --- # html_to_text.py ### `html_to_text.py` — 底层 HTML 清洗 最底层工具,被多个上层模块调用:HTML 转纯文本,对 `` 按行合并保留表格语义,清理 CSS/JS/隐藏元素/` ` 等噪音。 ## 代码 ```python # -*-coding:utf-8-*- # 功能:将HTML文本(含复杂表格)清洗转换为纯文本,去除标签、样式、脚本、注释等冗余内容 import re from bs4 import BeautifulSoup, Comment # 正则表达式:匹配需要在末尾添加换行符的HTML闭合标签,用于文本分段 brs_pattern = re.compile("||
|
||||||||

|
|||||||||||||||") class Html2txt(): """HTML转纯文本工具类""" def _html_text(self, _html): """ 私有方法:提取HTML中的纯文本,并替换换行符为空格 :param _html: HTML字符串 :return: 处理后的纯文本 """ # 解析HTML soup = BeautifulSoup(_html, "lxml") # 提取纯文本内容 _text = soup.get_text() # 替换所有换行符为空格,去除首尾空白 return re.sub(r"(\r\n)|\n", " ", _text).strip() def _table_text(self, table): """ 私有方法:专门处理HTML表格,规整表格内容为纯文本(处理单元格、行列对齐) :param table: BeautifulSoup的table节点对象 :return: 处理后的表格纯文本 """ # 查找嵌套表格,有则直接提取文本返回 _tables = table.find_all("table") if _tables: return table.get_text() # 获取所有行 trs = table.find_all("tr") if trs: for tr in trs: # 获取当前行所有单元格 tds = tr.find_all("td") new_tds = [] if tds: for td in tds: # 格式化单元格HTML,去除多余换行 _html = td.prettify() _html = re.sub(r"(\r\n+)|\n+", "", _html) # 匹配标签并添加换行,用于分段 brs = brs_pattern.findall(_html) for br in set(brs): _html = _html.replace(br, br + "\n") # 按换行分割处理 _brs = re.split(r"\n+", _html) # 修正末尾闭合标签位置 if _brs[-1] == "": _brs.pop(-1) _brs[-1] = _brs[-1] + "" # 过滤空内容并去除空白 _brs = [_br.strip() for _br in _brs if _br and _br.strip()] # 再次修正闭合标签 if _brs[-1] == "": _brs.pop(-1) _brs[-1] = _brs[-1] + "" new_tds.append(_brs) if new_tds: # 计算单元格最大列数,用于对齐不规则表格 _len = [len(t) for t in new_tds] _max = max(_len) data = [] _ldiff = [_l for _l in _len if _max != _l] if _ldiff: # 补全短单元格,使行列对齐 re_tds = [] for t in new_tds: diff_len = _max - len(t) if diff_len: for _ in range(0, diff_len): t.append("") re_tds.append(t) # 行列转置并拼接 for i in [list(t) for t in zip(*re_tds)]: data.append("".join(i)) elif _max > 1: try: # 正常行列转置 for i in [list(t) for t in zip(*new_tds)]: data.append("".join(i)) except: print("****", re_tds) else: # 单行数据直接拼接 data = [" ".join([k[0].strip() for k in new_tds if k[0]])] # 提取每个单元格纯文本 data = [self._html_text(d) for d in data] # 用处理后的文本替换原表格行 _re_str = "\n".join(data) tr.replace_with(_re_str) # 返回最终表格文本 return table.get_text() def clear_tables(self, s): """ 递归清理HTML中的所有表格,替换为规整文本 :param s: HTML字符串 :return: 清理表格后的文本 """ soup = BeautifulSoup(s, "lxml") # 移除HTML注释内容 comments = soup.findAll(text=lambda text: isinstance(text, Comment)) [comment.extract() for comment in comments] # 查找所有table标签 tables = soup.findAll("table") _text = soup.get_text() if tables: for table in tables: # 跳过嵌套表格 if table.findAll("table"): continue # 处理单个表格 _text = self._table_text(table) if _text: # 用纯文本替换原table标签 table.replace_with(_text) # 递归处理剩余表格 _text = soup.get_text() self.clear_tables(_text) return _text def clean_html(self, s): """ 对外核心方法:完整清洗HTML,转换为规范纯文本 :param s: 原始HTML字符串 :return: 最终纯文本 """ # 匹配") # 还原HTML转义字符 s = re.sub("<", "<", s) s = re.sub(">", ">", s) s = re.sub("&", "&", s) # 移除", "", s) # 移除设置了隐藏样式(display:none)的HTML元素 s = re.sub("(?is)<[^<]*?display\s*\:\s*none[^>]*?>[^<]*?", "", s) # 移除下拉选择框.*?", "", s) # 移除CSS样式内容 s = style_filter.sub("", s) # 单元格标签后添加空格分隔 s = re.sub(r"", " ", s) # 统一表格表头为 s = re.sub("", "", s) s = re.sub(r"", " ", s) # 关键标签后添加换行,实现文本分段 brs = brs_pattern.findall(s) for br in set(brs): s = s.replace(br, br + "\n") # 清理所有表格 _text = self.clear_tables(s) # 移除IE条件注释 _text = re.sub("(?is)", "", _text) _text = re.sub("(?is)", "", _text) # 统一换行符为Windows格式 \r\n _text = re.sub(r"\n", "\r\n", _text) # 合并多余空格、制表符、换行符 _text = re.sub(r"[ \f\v]{2,}", " ", _text) _text = re.sub(r"\t{2,}", "\t", _text) _text = re.sub(r"(\r\n){2,}", "\r\n", _text) _text = re.sub(r"\r\n\s+", "\r\n", _text) # 去除空白特殊字符   _text = re.sub(r"\xa0\xa0", "", _text) _text = re.sub(r"\r\n\xa0", "\r\n", _text) _text = re.sub(r"\xa0\xa0", "", _text) # 去除首尾空白并返回 return _text.strip() if __name__ == '__main__': # 测试:读取本地HTML文件并转换为纯文本 filepath = r"/Users/ziguangchu/source/python/clawler_data/data/ardata/sch_00131/detail_e49385645df507c84d6fd149cc93cff1.html" with open(filepath, "r", encoding="utf-8", errors='ignore')as f1: s = f1.read() # 执行转换 res = Html2txt().clean_html(s) print(res) ``` --- **项目分区导航**:[[05-cjob_model|cjob_model]] ⬅️ | 06-html_to_text | ➡️ [[00-auto_gen|auto_gen]]