根本原因是html.fromstring()默认按utf-8字节流解析,不自动探测编码或容错;输入为bytes时须确保utf-8编码,为str时需避免非法字符,且应优先检查bom和实际编码。

为什么 html.fromstring() 有时解析出空树或报错
根本原因不是 HTML 写得“不对”,而是 html.fromstring() 默认把输入当作 UTF-8 字节流处理,但你传的可能是字符串(str)、带 BOM 的文件、或 GBK 编码的响应体。它不会自动探测编码,也不会 fallback 到浏览器式容错。
常见错误现象:AttributeError: 'NoneType' object has no attribute 'xpath'(根节点为 None),或解析后 .xpath('//div') 返回空列表,明明源码里有 <div>。
<ul>
<li>如果输入是 <code>bytes,确保它是 UTF-8 编码;如果不是,先用对应编码解码成 str,再交给 html.fromstring()
str(Python 3 下通常是 Unicode),lxml 会直接解析,但若字符串含非法字符(如未转义的 在文本中),可能截断或静默失败
print(repr(html_bytes[:100])) 看开头几个字节,确认有没有 \xef\xbb\xbf(UTF-8 BOM)或 \xff\xfe(UTF-16 LE)
html.fromstring() 和 etree.fromstring() 选哪个
二者底层都走 libxml2,但语义和默认行为不同:html.fromstring() 是 HTML 专用入口,内置了标签修复(比如自动补全 <table><tr><td>)、忽略声明、容忍自闭合错误;<code>etree.fromstring() 是 XML 解析器,遇到 <img alt="Python lxml html.fromstring 解析HTML为XML树" > 不闭合或属性没引号就直接抛 XMLSyntaxError。
使用场景很明确:只要源是网页 HTML(哪怕写得烂),必须用 html.fromstring();只有当你确定输入是严格 XML(比如 RSS、SOAP 响应),才用 etree.fromstring()。
立即学习“Python免费学习笔记(深入)”;
-
html.fromstring()会把<br>、<input>这类 void 元素正确识别为单标签,而etree.fromstring()会要求写成<br> -
html.fromstring()自动将文档编码声明(如<meta charset="gbk">锛夌撼鍏ヨВ鐮佸弬鑰冿紝etree.fromstring()瀹屽叏涓嶇湅杩欎釜 - 鎬ц兘涓婂樊寮傚井涔庡叾寰











