用Python从URL读取和解析JSON文件

在Python中从URL读取JSON可将远程响应立即转换为可用的数据。使用urllib.request获取响应,然后将其正文传递给json.loads以获取字典或列表。此模式适用于公共API、托管的配置文件以及独立于代码变化的数据集。

Python从URL读取JSON示例

输出:

输出将显示在这里...

输出:

Squad: Super Hero Squad
Members: 3

示例工作原理

  1. urllib.request.urlopen(url)发送同步GET请求并返回HTTP响应;with块在结束后关闭连接。
  2. response.read()以原始字节形式返回正文。json.loads直接接受字节,因此不需要手动执行.decode("utf-8")步骤。
  3. 解析将JSON对象转换为Python dict,可通过data["squadName"]进行索引访问,通过len(data["members"])获取数量。

在此运行时中,urlopen是同步的,因此不需要awaitasyncio,即使许多教程将网络调用包装在异步代码中。

json.load 与 json.loads 的区别

两个函数都将JSON反序列化为Python对象;区别在于它们读取的来源。

函数输入使用时机
json.loads(...)strbytes内容已在内存中,如response.read()
json.load(...)文件或流对象有打开的句柄,如open(path)或响应本身

此处json.loads(response.read())json.load(response)产生相同的dict。常见错误是传入错误类型:将字符串传给json.load或将文件对象传给json.loads会引发AttributeErrorTypeError

在Run Details中查看JSON请求

程序完成后打开Run Details。它将脚本发出的网络请求与运行时为执行代码加载的包分开显示。

Run Details信号含义
Requests显示对raw.githubusercontent.com的GET请求,状态为200JSON文件已通过网络成功获取
请求时间(ms)获取本身花费的时间,与解析分开计算
请求返回403/404、被阻止或失败URL不可访问或未启用CORS,代码从未收到数据
Packages为空(“No runtime packages”)jsonurllib是标准库,未安装任何内容

Packages部分为空证明此方法无需安装依赖。导入beautifulsoup4pandas的示例会在此列出加载的包,如网页抓取示例;使用标准库读取JSON则不会列出任何包。

在浏览器中从URL读取只有在端点发送CORS标头时才有效。上述文件是GitHub raw上支持CORS的文件;没有这些标头的跨域URL会在代码运行前被阻止,表现为请求失败而不是JSONDecodeError

从URL读取JSON的常见错误

错误:两次读取响应流。

错误示例:

raw = response.read()
data = json.loads(response.read())

正确示例:

data = json.loads(response.read())

原因:urlopen返回只能消费一次的流;第二次调用read()返回空字节。

错误:对已解析的JSON数组调用.get()

错误示例:

data = json.loads(response.read())
first = data.get("name")

正确示例:

data = json.loads(response.read())
first = data[0] if isinstance(data, list) else data["name"]

原因:顶层JSON数组解析为Python列表,列表没有.get方法;需要使用索引访问。

错误处理和缺失键

urlopen对4xx和5xx响应抛出HTTPError,但错误对象仍可读取,因此可以通过用try/except捕获来解析JSON错误正文:

from urllib.error import HTTPError

try:
    with urllib.request.urlopen(url) as response:
        data = json.loads(response.read())
except HTTPError as err:
    data = json.loads(err.read())

对于可选字段,使用data.get("key")返回None而不是引发KeyError。标准库json模块可安全解析不可信的输入,因此读取JSON时永远不要使用eval()

FAQ

如何在Python中读取JSON文件?

对于远程文件,使用urllib.request.urlopen(url)打开并将字节传递给json.loads。对于磁盘上的文件,使用with open(path) as f: data = json.load(f)。两者都返回Python dict或列表。

json.load和json.loads有什么区别?

json.load从文件或流对象读取,而json.loadsstrbytes值读取。末尾的”s”代表string(字符串)。当内容已在内存中时使用loads

在Python中读取JSON需要requests库吗?

不需要。urllib.requestjson都是标准库,因此无需任何安装即可获取和解析JSON。requests库添加了.json()辅助方法和会话管理等便利功能,但它是第三方依赖。

Python中的JSON是什么?

JSON是结构化数据的文本格式。Python将JSON对象映射为dict,将数组映射为列表,将基本类型映射为strintfloatboolNone——这正是json.loads解析后返回的内容。