kp-007

HTML 解析实战:BeautifulSoup 与 lxml

核心 ≈ 30 分钟 BeautifulSouplxml解析选择器字段抽取

前置知识

本文基于模型知识整理,建议核对官方文档(见 参考资料)。

一句话定义

BeautifulSoup 提供「对人类友好」的树查询 API,lxml 提供底层的高速解析引擎;两者组合(BS4 用 lxml 作 parser)是静态页字段抽取的常规配置。

为什么重要

解析是从「一坨 HTML」到「结构化字段」的关键一跳。解析代码的写法直接决定站点改版后的维护成本:锚点选得好,改版只改一行;锚点选得差,全部重写。

前置知识

kp-003(DOM 树与选择器)、kp-006(拿到 HTML 文本)。

核心概念

  • parser 选择:html.parser(内置、慢)、lxml(快、需安装)、html5lib(最宽容、最慢)。
  • find / find_all:单数/复数查询,参数可为标签名、attrs、CSS 选择器(select)。
  • 节点属性:tag.name、tag.get("href")、tag.get_text(strip=True)。
  • 相对定位:先锁定列表容器,再在容器内找子节点,避免全局误命中。
  • None 防御:find 找不到返回 None,链式调用前必须判空。

原理与机制

标准抽取模式:容器定位 → 单元遍历 → 单元内相对取字段。

from bs4 import BeautifulSoup

soup = BeautifulSoup(html, "lxml")
items = []
for pod in soup.select("article.product_pod"):        # ① 容器/单元定位
    a = pod.select_one("h3 a")                        # ② 单元内相对定位
    price = pod.select_one("p.price_color")
    rating = pod.select_one("p.star-rating")
    items.append({
        "title": a["title"] if a else None,           # ③ 判空 + 优先读属性
        "price": price.get_text(strip=True) if price else None,
        "rating": rating["class"][1] if rating and len(rating["class"]) > 1 else None,
    })

选锚点的优先级(抗改版能力从高到低):data-* 属性 > 语义 class(如 product_pod)> 结构位置(nth-child)。标题类文本优先读 title/alt 属性而非内嵌文本——站点常把长文本截断显示在标签里,完整值在属性上。

实例或案例

books.toscrape.com 完整落地:每页 20 本,抽出 title/price/rating/链接四字段,翻页逻辑交给 kp-010,落库交给 kp-011。练习目标:10 分钟内从「右键检查」到「跑出 20 行字典列表」。

常见误区

  • 误区一:get_text() 结果带满屏空白。 列表结构中标签间有换行缩进,必须 get_text(strip=True) 或后续 strip。
  • 误区二:不判空直接 a["title"]。 改版或个别缺字段时直接 TypeError 崩掉整个任务;统一用 if x else None。
  • 误区三:解析慢就抱怨 BS4。 换 lxml parser 通常有数倍提升;仍慢则该考虑用 kp-009 的接口路线而非死磕 HTML。

自测题

  1. find 与 find_all 返回类型差异及代码含义?

答:find 返回单个节点或 None;find_all 返回列表(可能为空)——前者要判空,后者要判长度。

  1. 为什么优先读 a["title"] 而不是 a.get_text()?

答:显示文本可能被截断(如加省略号),属性里通常是完整原文。

  1. 解析器性能排序?

答:lxml > html.parser > html5lib;lxml 同时是速度与容错的常见折中首选。

与其他知识点的关系

kp-008 给出 XPath 这一更强的定位语言;kp-010 把「一页的解析」扩成「整站的采集」;kp-011 消费本篇产出的字典列表。

延伸阅读

BeautifulSoup 官方文档「Quick Start」与「Searching the tree」两节。

相关知识点

学习进度