Python对HTML进行预处理的全流程

 更新时间:2026年09月18日 08:39:24   作者:detayun  
HTML 预处理,本质是在正式解析之前,对原始网页做清洗、规整,它不等同于 HTML 压缩,压缩更多是为减小体积,本文结合爬虫实战,梳理一套完整的 HTML 预处理流水线,覆盖从原始 bytes 到干净文本的全流程,需要的朋友可以参考下

前言

爬虫开发中,拿到 HTTP 返回的 HTML 原始源码并不是终点。原始页面经常夹杂 BOM 标记、多余空白、无效注释、转义字符、不规范标签,直接拿去解析、提取文本、做相似度对比或者文件类型判断,很容易踩各种隐形大坑。

HTML 预处理,本质是在正式解析之前,对原始网页做清洗、规整。它不等同于 HTML 压缩,压缩更多是为减小体积;预处理目标更宽泛:修复脏数据、消除干扰项,为后续 XPath / CSS选择器 / 文本提取提供干净可靠的输入。

本文结合爬虫实战,梳理一套完整的 HTML 预处理流水线,覆盖从原始 bytes 到干净文本的全流程。

HTML预处理一般要做哪些工作

一套标准预处理流程顺序(非常关键,顺序不能乱):

  1. 二进制预处理:剔除 UTF-8 BOM、截断超长响应、过滤无效二进制头部
  2. 编码自动识别 & 解码:把 bytes 转为字符串,解决网页乱码
  3. 清洗干扰内容:移除注释、多余换行/空格,按需压缩空白
  4. 标签规范化:补全残缺标签、处理转义字符
  5. 可选过滤:移除无用标签(script/style/noscript),减少解析压力

重点提醒:操作顺序建议:bytes处理 → 解码 → 文本清洗。不要先解码再处理BOM,会引入不必要的\ufeff字符。

第一步:原始二进制处理,清除UTF-8 BOM

网页由Windows服务器或记事本生成时,很容易在最前面带上b'\xef\xbb\xbf'
它不属于HTML正文,但是会干扰魔数判断、前缀匹配,lstrip()无法自动移除。

def strip_bom_and_prefix_whitespace(raw_bytes: bytes) -> bytes:
    # 移除UTF-8 BOM
    if raw_bytes.startswith(b"\xef\xbb\xbf"):
        raw_bytes = raw_bytes[3:]
    # 剔除文档开头空白(空格、换行、tab、回车)
    raw_bytes = raw_bytes.lstrip(b" \r\n\t")
    return raw_bytes

这一步对应我们之前写的detect_file_type函数,在解码之前执行,性能更高,规避解码异常

第二步:编码识别,bytes转文本

很多网页Content-Type里写的编码和页面meta声明不一致,直接用resp.content.decode("utf-8")大概率乱码。
推荐使用cchardet/chardet自动探测编码。

pip install cchardet
import cchardet

def decode_html(raw_bytes: bytes) -> str:
    detect_result = cchardet.detect(raw_bytes)
    encoding = detect_result["encoding"] or "utf-8"
    try:
        return raw_bytes.decode(encoding)
    except Exception:
        # 探测编码失败时兜底
        return raw_bytes.decode("utf-8", errors="replace")

小技巧:可以优先从response headers、html meta标签提取charset,优先级高于自动探测,准确率更高。

第三步:文本清洗,去除注释与多余空白

这里要区分两种场景:

  1. 保留页面结构,只删除注释、合并多余空白(推荐,用于解析)
  2. 强压缩,删除标签间空白(适合存储、文本比对,不建议用于解析)

❌ 禁止简单正则全局删除空白,<pre> <textarea> <script> <style>内部的空白不能随意清除。

import re
import htmlmin

def clean_html_text(html: str, remove_comments=True) -> str:
    if remove_comments:
        # 删除html注释,注意:不会处理script内部注释
        html = re.sub(r"<!--[\s\S]*?-->", "", html)
    # 轻量清洗,保留pre/script/style内部格式
    html = htmlmin.minify(html, remove_comments=False, remove_all_empty_space=False)
    return html

按需移除无用标签(爬虫常用)

如果我们只需要提取正文文本,不需要JS、CSS,可以直接删除script、style标签,减少解析开销:

from bs4 import BeautifulSoup

def remove_useless_tags(html: str) -> str:
    soup = BeautifulSoup(html, "html.parser")
    for tag in soup(["script", "style", "noscript"]):
        tag.decompose()
    return str(soup)

注意:移除script/style会改变页面DOM结构,如果你的业务需要执行JS、提取内嵌CSS,不能使用这一步。

完整预处理流水线示例(爬虫实战)

组合上面所有步骤,搭配requests,形成可直接复用的预处理函数:

import requests
import cchardet
import htmlmin
from bs4 import BeautifulSoup

def preprocess_html(resp: requests.Response) -> str:
    # 1. 获取原始二进制,清理BOM和前置空白
    raw_bytes = resp.content
    if raw_bytes.startswith(b"\xef\xbb\xbf"):
        raw_bytes = raw_bytes[3:]
    raw_bytes = raw_bytes.lstrip(b" \r\n\t")

    # 2. 编码探测并解码
    detect_result = cchardet.detect(raw_bytes)
    encoding = detect_result["encoding"] or "utf-8"
    try:
        html_str = raw_bytes.decode(encoding)
    except Exception:
        html_str = raw_bytes.decode("utf-8", errors="replace")

    # 3. 删除注释
    html_str = re.sub(r"<!--[\s\S]*?-->", "", html_str)

    # 4. 移除script/style标签(按需开启)
    soup = BeautifulSoup(html_str, "html.parser")
    for tag in soup(["script", "style"]):
        tag.decompose()
    html_str = str(soup)

    # 5. 轻量清洗多余空白
    html_str = htmlmin.minify(html_str, remove_comments=False, remove_all_empty_space=False)
    return html_str

if __name__ == "__main__":
    r = requests.get("[https://example.com](https://example.com)")
    clean_html = preprocess_html(r)
    print(clean_html)

常见踩坑点

  1. BOM处理时机:BOM必须在bytes阶段处理;解码后会变成\ufeff,容易被忽略,干扰文本匹配。
  2. 编码冲突:HTTP Header的charset、meta标签charset、页面实际编码三者可能不一致,自动探测只能做兜底,优先解析meta标签。
  3. 正则不能万能:不要手写正则去删除标签,HTML不是规则文本,正则极易破坏DOM;标签删除交给BeautifulSoup。
  4. 预处理≠压缩:做Xpath/CSS选择器解析时,不要使用强压缩模式,虽然体积更小,但调试困难,极少提升解析速度。
  5. 转义字符&lt; &amp;这类实体,一般保留原样;只有提取纯文本展示时才调用html.unescape()
  6. 异常页面:部分网页存在不闭合标签,BS4会自动修复,这也是预处理的一部分。

不同业务场景预处理策略

  • 网页文件类型判断:只做二进制BOM清洗,不解码,直接用原始bytes做魔数判断(就是前面detect_file_type方案)
  • DOM解析、字段提取:BOM清洗 → 解码 → 删除注释 → 移除script/style → 轻量空白规整
  • 网页归档存储:在上面基础上,开启htmlmin强压缩,减小存储体积
  • 网页正文相似度比对:全部预处理完成后,再提取纯文本,消除换行空格带来的干扰

小结

HTML预处理不是简单的“删空格”,而是一套分层清洗流水线:二进制预处理优先,然后处理编码,再做DOM清洗
根据业务选择清洗力度:类型检测尽量不解码;DOM解析用BS4安全移除无用标签;归档场景再开启压缩。

在爬虫项目中,把BOM清洗、编码探测、注释清理、无用标签移除封装成独立预处理函数,可以极大减少后续解析环节的各种诡异bug。

以上就是Python对HTML进行预处理的全流程的详细内容,更多关于Python对HTML预处理的资料请关注脚本之家其它相关文章!

相关文章

  • python导出mysql指定binlog文件实现demo

    python导出mysql指定binlog文件实现demo

    这篇文章主要介绍了python导出mysql指定binlog文件实现demo,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-12-12
  • python中pathlib模块的基本用法与总结

    python中pathlib模块的基本用法与总结

    这篇文章主要给大家介绍了关于python中pathlib模块的基本用法与总结的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者使用python具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2020-08-08
  • Python itertools中accumulate函数用法及使用运用详细讲解

    Python itertools中accumulate函数用法及使用运用详细讲解

    这篇文章主要介绍了Python的itertools库中的accumulate函数,该函数可以计算累积和或通过指定函数进行累积运算,文中通过代码将用法介绍的非常详细,需要的朋友可以参考下
    2025-02-02
  • Python解析toml配置文件的方法分享

    Python解析toml配置文件的方法分享

    在开发过程中,配置文件是少不了的,而且配置文件是有专门的格式的,比如:ini,yaml,toml等等。本文带大家来看看Python如何解析toml文件,需要的可以参考一下
    2022-09-09
  • python+opencv实现论文插图局部放大并拼接效果

    python+opencv实现论文插图局部放大并拼接效果

    在做图像数据标注时,很难一次就做到精准标注,如果目标比较小,即使微调也难以做到精准,所以就需要另外一个窗口对标注区域进行局部放大以方便微调,这篇文章主要给大家介绍了关于python+opencv实现论文插图局部放大并拼接效果的相关资料,需要的朋友可以参考下
    2021-10-10
  • pycharm开发一个简单界面和通用mvc模板(操作方法图解)

    pycharm开发一个简单界面和通用mvc模板(操作方法图解)

    这篇文章主要介绍了pycharm开发最简单的界面和通用mvc模板的方法,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-05-05
  • python 中[0]*2与0*2的区别说明

    python 中[0]*2与0*2的区别说明

    这篇文章主要介绍了python 中[0]*2与0*2的区别说明,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-05-05
  • django authentication 登录注册的实现示例

    django authentication 登录注册的实现示例

    本文主要介绍了使用Django内置的authentication功能实现用户注册和登录功能,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2024-11-11
  • python图形开发GUI库pyqt5的详细使用方法及各控件的属性与方法

    python图形开发GUI库pyqt5的详细使用方法及各控件的属性与方法

    这篇文章主要介绍了python图形开发GUI库pyqt5的详细使用方法及各控件的属性与方法,需要的朋友可以参考下
    2020-02-02
  • Python内置函数locals和globals对比

    Python内置函数locals和globals对比

    这篇文章主要介绍了Python内置函数locals和globals对比,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-04-04

最新评论