最快方式是用浏览器开发者工具查看dom树:按ctrl+shift+i(windows/linux)或cmd+option+i(mac)打开,切换到elements面板,左侧即为浏览器解析后的实时dom树,支持高亮、复制选择器、观察层级与属性。

用浏览器开发者工具直接看 DOM 树
这是最快、最可靠的方式,不需要写代码,也不依赖第三方库。DOM 树就是浏览器实际解析后生成的结构,和原始 HTML 可能不完全一致(比如自动补全 <tbody>、修正嵌套错误)。
<p>常见错误现象:你写的 <code>select('div.content p') 在 Python 里没结果,但网页上明明有——大概率是原始 HTML 没闭合标签,浏览器自动修复了,而解析器没修,导致层级对不上。
- 按
Ctrl+Shift+I(Windows/Linux)或Cmd+Option+I(Mac)打开开发者工具 - 切到
Elements面板,左侧就是实时 DOM 树 - 鼠标悬停在 DOM 节点上,页面对应区域会高亮;右键节点可“Copy selector”或“Copy XPath”,直接拿去代码里用
- 注意观察缩进层级、
class和id属性值,它们才是真实存在的定位依据
用 BeautifulSoup 解析时要注意 parser 的行为差异
BeautifulSoup 不是直接读 DOM,而是解析原始 HTML 字符串。不同 parser 对不规范 HTML 的容忍度和修复策略完全不同,直接影响树结构。
使用场景:你拿到的是服务器返回的 raw HTML(比如 requests.get(url).text),不是浏览器渲染后的结果。
-
html.parser:Python 内置,容错中等,速度快,适合大多数静态页 -
lxml:需pip install lxml,修复更激进(比如自动加<tbody>),XPath 支持好,但可能把原始结构“改过头” <li> <code>html5lib:最接近浏览器行为,会模拟 HTML5 规范修复,但慢,且不支持 XPath - 别省略 parser 参数——写成
BeautifulSoup(html, 'html.parser'),否则默认用系统第一个可用 parser,行为不可控 -
//article/div[2]/section/p[1]:从任意<article></article>开始,找第 2 个<div> 下的 <code><section></section>里的第 1 个<p></p> -
//div[@class="post-content"]//h2[1]:匹配 class 为post-content的<div> 内部任意深度的第一个 <code><h2></h2> - 注意:XPath 返回的是
list,即使只匹配一个也要取[0],否则调用text_content()会报AttributeError - 属性值含空格或特殊字符?用
contains(@class, "item")替代精确匹配 - 用
node.parent.name看父标签名,node.parent.attrs看父节点属性 -
for child in node.children:—— 过滤掉空白文本节点:if child.name: ... - 检查兄弟节点顺序:
list(node.previous_siblings)和list(node.next_siblings)返回的是逆序/正序列表,不是单个节点 - 调试时打印
node.name和node.get_text()[:20],比看整个 HTML 更快定位异常节点
用 lxml + XPath 定位深层嵌套元素
当目标元素藏在多层 <div> 套娃里,CSS 选择器容易写长且难维护,<code>xpath() 更精准、表达力更强。
性能影响:lxml 解析速度明显快于 BeautifulSoup,尤其处理大文件或批量任务时。
手动遍历 DOM 树确认父子关系
当你不确定某个元素是否真是目标节点的直接父级,或者想验证 find_parent() / find_next_sibling() 的行为,手写一段遍历脚本能快速厘清。
容易踩的坑:find_all() 默认只查直接子节点(recursive=False),但很多人误以为它搜整棵树;contents 包含文本节点和注释,children 只返回元素节点。











