4人参与 • 2026-09-18 • Python
在爬虫、文件解析、http响应处理场景里,经常会遇到一种诡异问题:肉眼看文本完全正常,但程序判断逻辑莫名失效。典型案例:html页面明明是标准文档,却因为开头多出3个字节,被误判为非html类型。罪魁祸首就是 utf-8 bom。
很多开发者有误区:utf-8本身不需要bom。utf-8 bom只是微软体系(windows记事本等)为了标记编码加入的约定,并不是utf-8标准强制要求。它的二进制为 b'\xef\xbb\xbf',占3字节,放在文件最前面。
0xef 0xbb 0xbf 前缀,也就是utf-8 bom。举个例子:
# 带bom的html原始二进制 data = b'\xef\xbb\xbf<!doctype html><html>...</html>' print(data.lstrip()) # 输出还是 b'\xef\xbb\xbf<!doctype html>...' # lstrip() 只能删除空白字符,不会移除bom字节!
这就是我在http文件类型检测函数踩的坑:content-type 返回text/html,但正文头部带bom,前缀匹配直接失败,识别成txt。
先判断是否以bom字节开头,如果是直接切片去掉前3字节。适合直接读取bytes的场景,比如requests响应原始内容。
def strip_utf8_bom(data: bytes) -> bytes:
if data.startswith(b'\xef\xbb\xbf'):
return data[3:]
return data
raw = b'\xef\xbb\xbfhello world'
res = strip_utf8_bom(raw)
print(res) # b'hello world'
适合我们之前写的detect_file_type文件类型判断逻辑,二进制阶段清除bom,不需要解码,性能更好,也避免解码异常。
python内置编码 utf-8-sig,会自动识别并丢弃utf-8 bom,不需要手动写切片逻辑。
# 读取本地文件
with open("test.html", "r", encoding="utf-8-sig") as f:
text = f.read()
# bytes转字符串时使用
raw_bytes = b'\xef\xbb\xbf<!doctype html>'
text = raw_bytes.decode("utf-8-sig")
print(text)
注意区分:
utf-8:不会自动移除bom,bom会变成 \ufeff 字符留在文本里;utf-8-sig:自动移除bom,得到干净文本。如果已经解码成字符串,bom会变成unicode零宽字符 \ufeff,可以直接替换:
text_with_bom = "\ufeff<!doctype html>"
clean_text = text_with_bom.replace("\ufeff", "")
print(clean_text)
缺点:会扫描全文替换,只适合小文本;大文件/二进制场景不推荐。
很多网站返回html时会带上utf-8 bom。用requests拿到response.content是原始bytes。
如果直接用原始字节做魔数、标签前缀判断,bom会干扰匹配。
就像前面文件类型检测代码,处理顺序建议:二进制先剔除bom,再去除空白,再做前缀匹配:
def strip_bom_and_whitespace(data: bytes) -> bytes:
# 第一步移除utf8 bom
if data.startswith(b'\xef\xbb\xbf'):
data = data[3:]
# 第二步去除前置空白:空格、换行、回车、tab
return data.lstrip(b' \r\n\t')
# 测试bom+换行场景
html_bin = b'\xef\xbb\xbf\n <html><body></body></html>'
clean_bin = strip_bom_and_whitespace(html_bin)
print(clean_bin.startswith(b'<html')) # true
bytes.lstrip() 不能自动删除bom,bom不属于空白字符;utf-8 和 utf-8-sig 是两个编码,打开文件选错就会残留\ufeff;\ufeff,极少数业务场景下这个字符是业务正文,直接替换会破坏内容;写入带bom的utf8文件示例:
content = "测试文本"
with open("out.txt", "wb") as fp:
fp.write(b'\xef\xbb\xbf')
fp.write(content.encode("utf-8"))
utf-8 bom只是历史遗留标记,不是utf-8标准一部分。在python里分两种场景处理:
b'\xef\xbb\xbf' 切片去除;utf-8-sig编码自动处理。在爬虫、文件检测这类底层二进制判断场景,推荐bytes预处理,可以避免解码带来的性能损耗与编码异常,也是我在http文件类型识别函数里最终采用的方案。
到此这篇关于python如何处理utf-8 bom编码标记的文章就介绍到这了,更多相关python处理utf-8 bom内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
您想发表意见!!点此发布评论
版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。
发表评论