使用BeautifulSoup保留原始HTML实体的方法
关于BeautifulSoup保留原始HTML实体及写入文件的问题
1. 能否保留原始HTML实体?
可以,但需要调整解析或输出配置。默认情况下,BeautifulSoup会自动将HTML实体解码为对应字符(比如把"解码为",再进一步解码为"),导致原始实体丢失。要保留原始实体,有两种常用方案:
方案一:解析时禁用实体解析
使用lxml解析器并添加resolve_entities=False参数,解析过程中将不会解码任何实体:
from bs4 import BeautifulSoup # 禁用实体解析 soup = BeautifulSoup('<p class="test">&quot;Hello World!&quot; I said', "lxml", resolve_entities=False) print(soup.string) # 输出:'&quot;Hello World!&quot; I said'
方案二:输出时强制编码实体
如果解析阶段已完成实体解码,可通过formatter参数在输出时重新将字符编码为实体。使用formatter="html"会把HTML特殊字符(<、>、&、"、')转换为对应的实体:
from bs4 import BeautifulSoup soup = BeautifulSoup('<p class="test">&quot;Hello World!&quot; I said') # 编码后输出实体 print(soup.string.encode(formatter="html").decode("utf-8")) # 输出:'&quot;Hello World!&quot; I said'
2. 保留实体后写入文件的可行性
直接用f.write(str(soup))无法生成和原始文件完全一致的副本,原因有两点:
- BeautifulSoup默认会格式化HTML(比如添加缩进、换行),破坏原始排版
- 若解析时未正确保留实体,
str(soup)会输出解码后的字符而非原始实体
要生成完全一致的副本,建议:
- 解析时用
lxml并禁用实体解析 - 写入时直接输出解析后的原始内容,避免BeautifulSoup的自动格式化
修改后的代码如下:
from bs4 import BeautifulSoup from pathlib import Path original = Path("original.html") output = Path("duplicate.html") # 解析时禁用实体解析,减少排版修改 with open(original, "rt", encoding="utf8") as f: soup = BeautifulSoup(f, "lxml", resolve_entities=False, preserve_whitespace_tags=True) # 直接写入编码后的内容,避免格式化 with open(output, "wt", encoding="utf8") as f: f.write(soup.encode("utf-8").decode("utf-8"))
添加preserve_whitespace_tags=True可减少对标签内空格的修改,进一步贴近原始文件的排版。
内容的提问来源于stack exchange,提问作者Rick Manix
相关产品推荐
相关产品推荐

