HTMLParser中handle_data与handle_starttag需通过状态变量协同工作:进入目标标签时设标志(如self.in_price=True),退出时清除,期间handle_data捕获的内容才归属该标签;嵌套场景须用栈管理标签路径,避免内容错位。

HTMLParser 里 handle_data 和 handle_starttag 怎么配合提取结构化内容
直接调用 handle_data 拿到的只是纯文本碎片,没有上下文;光靠 handle_starttag 又不知道后续内容归属哪个标签。必须靠状态变量联动——比如进 <div class="price"> 时设 self.in_price = True,出 </div> 时清空它,中间所有 handle_data 的内容才可安全收进 price 字段。
常见错误是忽略嵌套:如果价格 div 里还有 <span>¥</span>,handle_data 会触发两次("¥" 和 "299"),但没做栈管理就容易把单位和数字拆开存错位置。建议用 self.tag_stack.append(tag) + self.tag_stack.pop() 跟踪当前路径。
HtmlAgilityPack 中 SelectNodes("//div[@class='item']") 返回 null 怎么办
不是 XPath 写错了,大概率是 HTML 不规范导致解析失败。HtmlAgilityPack 默认按严格 XML 规则解析,遇到 <img src="x"> 这类无闭合标签、或属性没引号(class=item)时会静默跳过部分节点。
解决方法只有两个:
立即学习“前端免费学习笔记(深入)”;
- 加载前先调用
doc.OptionFixNestedTags = true让它自动修复嵌套 - 用
doc.LoadHtml(htmlText.Replace("class=item", "class=\"item\""))预处理脏数据
别依赖 DocumentNode.InnerText 反推——它会把 script/style 里的内容也混进来,且丢失结构。
n8n 的 HTML 节点为什么 extract 出来全是空数组
关键看输入数据类型和字段名是否匹配。n8n 的 HTML 节点默认从 body 字段取 HTML 字符串,但 HTTP 请求节点返回的响应体实际在 response.body 或 json.body(取决于 Content-Type)。如果上游是 JSON 接口,却填了 body 当 JSON 属性名,就会读到 undefined。
验证步骤:
- 加个 Set 节点,把上一步输出整个写进
data字段,预览确认 HTML 确实存在 - CSS 选择器别写成
.product-price却忘了页面实际是span.product-price—— n8n 不报错,只默默不匹配 - “返回数组”开关没开,而目标元素有多个,结果只取第一个,容易误判为失败
lxml.etree 解析后用 xpath("//text()") 提取不到中文怎么办
根本原因是编码声明缺失或冲突。比如 HTML 里写了 <meta charset="gb2312">,但 lxml 默认用 utf-8 解码字节流,中文全变 。不能靠 etree.tostring(..., encoding="utf-8") 补救——那是输出编码,不是输入解码。
正确做法分两步:
- 读文件时显式指定编码:
with open("page.html", encoding="gb2312") as f: content = f.read() - 或用
etree.HTML(content.encode("gb2312"))强制传入 bytes,并确保 parser 支持该编码(需要装lxml时带 iconv 支持)
更稳妥的是统一转 UTF-8:用 chardet 先检测编码,再 decode + encode,否则 xpath 匹配文本时连空格都对不上。



















