Skip to content

解析器的使用

发请求只是第一步。真正有价值的工作,是把拿到的 HTML 或 JSON 解析成你想要的数据。

所以这一节的重点,不是“再发一次请求”,而是学会:

  • 从 HTML 中找节点
  • 从节点中提取文字和属性
  • 从 JSON 中取值

本节目标

  • 理解为什么需要解析器
  • 学会使用 lxml 解析 HTML
  • 学会使用 XPath 选取节点
  • 学会提取文本和属性
  • 学会使用 json.loads() 解析 JSON
  • 理解 jsonpath 的适用场景

为什么需要解析器

假设你请求到了一个网页,返回内容可能是这样的:

html
<html>
  <body>
    <h1>Python 学习空间</h1>
    <a href="https://example.com/detail">进入详情</a>
  </body>
</html>

你真正想要的也许只有:

  • 标题文本
  • 链接地址

这时候就不能只是把整页 HTML 打印出来,而是要学会“定位”和“提取”。

这就是解析器存在的意义。

HTML 和 JSON 的解析思路不同

如果返回的是 HTML

你通常要:

  • 找到目标节点
  • 提取节点文本
  • 提取节点属性

如果返回的是 JSON

你通常要:

  • 把字符串转成 Python 对象
  • 再根据键名和层级取值

所以你先要学会判断:当前响应到底是什么类型。

lxml 是什么

lxml 是 Python 中非常常用的 HTML/XML 解析库。

它在爬虫中的价值主要体现在:

  • 解析速度快
  • 和 XPath 搭配方便
  • 适合结构化提取数据

安装:

bash
pip install lxml

第一个 lxml 示例

python
from lxml import etree

html = """
<html>
  <body>
    <h1>Python 学习空间</h1>
    <a href="https://example.com/detail">进入详情</a>
  </body>
</html>
"""

tree = etree.HTML(html)

title = tree.xpath("//h1/text()")
link = tree.xpath("//a/@href")

print(title)
print(link)

输出结果:

text
['Python 学习空间']
['https://example.com/detail']

这里的重点有两个:

  • etree.HTML(html) 把 HTML 字符串解析成树结构
  • xpath() 用来定位并提取目标内容

XPath 是什么

XPath 可以理解成:在 HTML 树结构里查找节点的一种表达方式。

你可以先把它类比成:

  • 对 HTML 的“路径查询语言”

最常见的 XPath 用法

选中所有 h1

python
tree.xpath("//h1")

h1 的文本

python
tree.xpath("//h1/text()")

取链接的 href

python
tree.xpath("//a/@href")

选中某个 class 的元素

python
tree.xpath('//div[@class="item"]')

选中某个 id 的元素

python
tree.xpath('//div[@id="box"]')

节点文本提取

例如:

html
<p>这是段落内容</p>

提取方式:

python
tree.xpath("//p/text()")

输出结果:

text
['这是段落内容']

注意:XPath 返回的通常是列表,不一定是单个字符串。

属性提取

有很多有价值的数据并不在文本里,而是在属性中。

例如:

  • 链接地址在 href
  • 图片地址在 src

HTML:

html
<img src="cat.jpg" alt="猫">

提取图片地址:

python
tree.xpath("//img/@src")

输出结果:

text
['cat.jpg']

多个节点提取

例如:

html
<ul>
  <li>Python</li>
  <li>Linux</li>
  <li>Django</li>
</ul>
python
tree.xpath("//li/text()")

输出结果:

text
['Python', 'Linux', 'Django']

这在抓取列表页时非常常见。

一个完整 HTML 提取示例

python
from lxml import etree

html = """
<html>
  <body>
    <div class="course">
      <h2>Python 基础</h2>
      <a href="/course/python">查看详情</a>
    </div>
    <div class="course">
      <h2>Django 开发</h2>
      <a href="/course/django">查看详情</a>
    </div>
  </body>
</html>
"""

tree = etree.HTML(html)

titles = tree.xpath('//div[@class="course"]/h2/text()')
links = tree.xpath('//div[@class="course"]/a/@href')

print(titles)
print(links)

输出结果:

text
['Python 基础', 'Django 开发']
['/course/python', '/course/django']

这就是列表页提取的基础思路。

JSON 解析

如果响应不是 HTML,而是 JSON,就不需要 lxml,而是直接解析 JSON。

python
import json

text = '{"name": "小明", "age": 18, "city": "上海"}'
data = json.loads(text)

print(data["name"])
print(data["age"])

输出结果:

text
小明
18

json.loads() 的作用是:

  • 把 JSON 字符串转换成 Python 对象

解析嵌套 JSON

python
import json

text = """
{
  "code": 200,
  "data": {
    "user": {
      "name": "小明",
      "skills": ["Python", "Linux"]
    }
  }
}
"""

data = json.loads(text)

print(data["data"]["user"]["name"])
print(data["data"]["user"]["skills"][0])

输出结果:

text
小明
Python

这说明 JSON 解析本质上就是对 Python 字典和列表取值。

jsonpath 是什么

当 JSON 层级很深,或者你只想快速提取某些字段时,jsonpath 可能更方便。

你可以把它理解成:

  • 专门针对 JSON 的路径提取工具

它和 XPath 的思路有点像,只不过 XPath 面向 HTML/XML,jsonpath 面向 JSON。

零基础阶段你先知道它的定位就够了,先把普通 JSON 取值练熟更重要。

怎么判断该用 HTML 解析还是 JSON 解析

这是爬虫中非常重要的判断能力。

如果返回内容长得像页面源码

通常用:

  • lxml
  • XPath

如果返回内容长得像:

json
{"code": 200, "data": [...]}

通常用:

  • response.json()
  • json.loads()

所以第一步永远是先看返回内容到底是什么。

常见错误

1. XPath 写错,但还以为网站没数据

有时候不是网站没数据,而是你没选中正确节点。

2. 以为 xpath() 返回的一定是字符串

实际上通常返回的是列表。

3. 对 HTML 用 JSON 解析

如果内容本身不是 JSON,就不要乱用 json.loads()

4. 只会提文本,不会提属性

很多关键数据其实在:

  • href
  • src
  • data-*

这些属性里。

练习题

练习 1

写一段 HTML,包含标题和链接,并用 lxml 提取标题文本和链接地址。

练习 2

写一个包含多个 li 的 HTML,提取所有列表项文本。

练习 3

写一个包含 img 标签的 HTML,提取图片的 src 属性。

练习 4

自己定义一个 JSON 字符串,解析后取出其中两个字段。

练习 5

找一个接口返回的 JSON,分析它的层级结构,并手动写出取值路径。

本节小结

解析器的核心价值,是把原始响应转换成你真正需要的数据。

你这一节最重要的收获应该是:

  • 知道请求成功后下一步不是结束,而是解析
  • 会用 lxml + XPath 提取 HTML 中的文本和属性
  • 会用 json.loads() 解析 JSON
  • 知道什么时候该用 HTML 解析,什么时候该用 JSON 解析

只要这一层练熟,后面做列表页抓取、详情页抓取和接口解析时就会顺很多。

Built with VitePress.