🎯 一款可定制、具备反检测功能的云浏览器,由自主研发的 Chromium驱动,专为网页爬虫AI 代理设计。👉立即试用
返回博客

JMESPath网络抓取:声明性查询JSON API

Emily Chen
Emily Chen

Advanced Data Extraction Specialist

23-Jul-2026

TL;DR:

  • jmespath 以声明方式查询 JSON。 一个表达式将嵌套的 API 响应重塑为扁平记录——没有循环,没有手动字典遍历。
  • JSON API 是最干净的抓取目标。 许多网站从后端 JSON 端点构建其页面;获取该 JSON 数据,数据已结构化。
  • jmespath 不执行获取操作。 它没有 HTTP 客户端,也不解析 HTML;你将解码后的 JSON 对象交给它,它会进行查询。
  • 通过 Scrapeless 进行抓取,当 API 受到保护时。 实时运行通过 Scrapeless Universal Scraping API 获取了产品 API,然后使用 jmespath 选择、过滤和排序结果。
  • 一行中进行过滤和投影。 products[?price < \50`].title 返回了六个低于 $50 的产品;sort_by(products, &price)[0]` 返回了最便宜的产品。
  • 抓取方面免费开始。app.scrapeless.com 创建你的 Scrapeless API 密钥。

jmespath 是什么,以及它不是

jmespath 是一种用于 JSON 的查询语言。你编写一个描述你想要的形状的表达式,库会遍历文档并返回结果——投影从列表的每个元素中提取字段,过滤器仅保留匹配条件的元素,多重选择哈希将每个元素重建为更小的记录。它是 AWS CLI 用于其 --query 标志的相同表达语言,由 JMESPath 规范 标准化,并作为一个小型 Python 库提供。

它是一种查询语言,而不是爬虫。jmespath 没有 HTTP 客户端,不获取 URL,也不解析 HTML——它在你已经解码的 JSON 值上操作,由 JSON 数据交换标准 定义。因此,"jmespath 网页抓取" 设置包括两个层次:返回 JSON 的东西,以及重塑它的 jmespath。这很重要,因为现代网站上的大量数据是由页面在后台调用的后端 JSON API 提供的;直接访问该端点可以完全跳过 HTML 解析。当端点受到地理限制或限制速率时,本指南通过 Scrapeless Universal Scraping API 获取它。对于 HTML 抓取,Python 网页抓取教程 中介绍了选择器。

安装

jmespath 和 requests 是整个工具链。本指南编写时使用的版本是 jmespath 1.0.1:

bash Copy
pip install "jmespath==1.0.1" requests

将你的密钥保存在环境中,绝不要在源代码中:

bash Copy
export SCRAPELESS_API_KEY="sk_your_scrapeless_key"

通过 Scrapeless 获取 JSON API

获取层返回原始 JSON。由于端点提供 JSON,而不是渲染的页面,因此 js_render 保持关闭;Scrapeless API 处理请求、代理路由和端点前方的任何访问控制,并返回由 HTTP 语义标准 定义的正文。解码一次后,jmespath 接管:

python Copy
# fetch.py — 通过 Scrapeless 拉取 JSON API,然后查询它
import json
import os

import jmespath
import requests

resp = requests.post(
    "https://api.scrapeless.com/api/v2/unlocker/request",
    headers={"Content-Type": "application/json", "x-api-token": os.environ["SCRAPELESS_API_KEY"]},
    json={"actor": "unlocker.webunlocker", "input": {"url": "https://dummyjson.com/products?limit=10", "js_render": False}},
    timeout=120,
)
resp.raise_for_status()
payload = json.loads(resp.json()["data"])

print("页面中的产品数量:", jmespath.search("length(products)", payload))
print("首个标题:", jmespath.search("products[0].title", payload))
print("总可用数量:", jmespath.search("total", payload))

运行没有一条循环就读取了响应的形状:

text Copy
页面中的产品数量: 10
首个标题: Essence Mascara Lash Princess
总可用数量: 194

Scrapeless 调用是获取层——Universal Scraping API 返回 JSON 正文,payload 现在是 jmespath 可以查询的普通 Python 对象。

使用 jmespath 重塑和过滤

jmespath 的重点在于将冗长的响应转换为你想要的确切记录。使用多重选择哈希的投影重建每个产品;过滤表达式仅保留匹配项;sort_by 对它们进行排序——所有这些都是表达式,而不是过程代码:

python Copy
# query.py — 在三个表达式中重塑、过滤和排序
import json
import os

import jmespath
import requests

resp = requests.post(
"https://api.scrapeless.com/api/v2/unlocker/request",
    headers={"Content-Type": "application/json", "x-api-token": os.environ["SCRAPELESS_API_KEY"]},
    json={"actor": "unlocker.webunlocker", "input": {"url": "https://dummyjson.com/products?limit=10", "js_render": False}},
    timeout=120,
)
resp.raise_for_status()
payload = json.loads(resp.json()["data"])

records = jmespath.search("products[].{title: title, price: price, rating: rating}", payload)
under_50 = jmespath.search("products[?price < `50`].title", payload)
cheapest = jmespath.search("sort_by(products, &price)[0].{title: title, price: price}", payload)

print("记录数:", len(records))
print("第一条记录:", json.dumps(records[0], ensure_ascii=False))
print("低于$50的产品数:", len(under_50))
print("最便宜的产品:", json.dumps(cheapest, ensure_ascii=False))

每一行都是一个查询,完成循环的工作:

text Copy
记录数: 10
第一条记录: {"title": "精华睫毛膏 公主假睫毛", "price": 9.99, "rating": 2.56}
低于$50的产品数: 6
最便宜的产品: {"title": "红色指甲油", "price": 8.99}

这就是整个提取器:一次 POST 请求获取 JSON,三条表达式进行整形。多重选择哈希 {title: title, price: price} 是工作马,它丢弃不需要的字段并重命名保留的字段,因此您存储的正是所请求的内容。

获取您的免费计划 API 密钥:app.scrapeless.com

高级模式

  • 在投影之前过滤。 products[?rating > \4.5`].{title: title}` 首先保留匹配项,然后对其进行重塑;以这种方式排列管道可保持表达式的可读性和结果的简洁。
  • 使用 [] 扁平化嵌套列表。 当记录嵌套自己的列表时,products[].reviews[].rating 将每个产品的每条评论评分扁平化为一个列表——扁平操作符的作用相当于双重循环。
  • | 管道表达式。 products | length(@)sort_by(@, &price) | [0] 将一个结果链接到下一个表达式;@ 是当前节点,这就是如何将一个查询的输出馈送到另一个查询。
  • 防止缺少键。 jmespath 对不存在的路径返回 None 而不是引发错误,因此只在某些记录中存在的字段不会导致查询崩溃——存储时检查 None

故障排除

  • json.loads 在响应时引发异常。 端点返回了 HTML,而不是 JSON——通常是错误或阻止页面。确认 URL 是 JSON API 而不是调用它的 HTML 页面,并确保获取成功后再解码。
  • 投影返回空列表。 路径与文档形状不匹配。打印顶层键并逐级检查;JSON API 嵌套其数组在 productsresults 等键下,而不是在根级别。
  • 过滤器匹配不到任何内容。 过滤器中的数字和字符串需要使用反引号——price < \50`, 而不是 price < 50`。没有反引号时,值被读取为字段名称。
  • 结果保持了您不想要的字段。 您使用了无包装投影 products[] 而不是多重选择哈希。添加 .{title: title, price: price} 以仅选择要保留的字段。

结论

jmespath 通过不使用过程代码的层,成功地将 JSON 响应转换为记录:投影、过滤和排序作为单一表达式。获取 JSON 的层是获取——后端 API 是最干净的来源,而一次 Scrapeless POST 在跨越任何防护后返回其主体。将两者连在一起,一个冗长的产品馈送变成了您实际存储的四个字段。

创建一个免费的 Scrapeless 帐户以获取 API 密钥, 开发者文档 涵盖了 unlocker.webunlocker 参数。当您计划定期作业时,请查看 Scrapeless 定价

常见问题解答

问:jmespath 可以独立抓取网站吗?

不可以。jmespath 查询您已经拥有的 JSON 值;它没有 HTTP 客户端,也不获取 URL 或解析 HTML。将它与获取层配对——这里是 Scrapeless 通用抓取 API,返回 JSON 主体——并且 jmespath 将其重新整形为记录。

问:为什么抓取 JSON API 而不是 HTML 页面?

因为数据已经结构化地到达。许多页面从它们在后台调用的后端 JSON 端点渲染;访问该端点完全跳过了 HTML 解析和选择器维护,而 jmespath 将响应转化为您想要的记录。

问:jmespath 与 jsonpath 有什么不同?
两个查询 JSON,但 jmespath 有一个正式的规范和一个紧凑的表达语言,具有投影、过滤器、函数和重塑输出的多选哈希。它的多选语法——在查询中重命名和删除字段——使其成为提取的良好选择。

问:如果网站没有 JSON API,该怎么办?

那么就解析 HTML:通过 Scrapeless 获取渲染页面,并使用选择器库。jmespath 仅在源是 JSON 时适用;这两种方法涵盖了数据的两种形态。

问:抓取 JSON API 合法吗?

查询语言并未改变收集规则。仅抓取公共端点,遵循网站条款以及由 机器人排除协议 标准化的 robots 指令,保持抓取量在合理范围内,并根据适用的法律处理任何个人数据。

在Scrapeless,我们仅访问公开可用的数据,并严格遵循适用的法律、法规和网站隐私政策。本博客中的内容仅供演示之用,不涉及任何非法或侵权活动。我们对使用本博客或第三方链接中的信息不做任何保证,并免除所有责任。在进行任何抓取活动之前,请咨询您的法律顾问,并审查目标网站的服务条款或获取必要的许可。

最受欢迎的文章

目录