首页 / Python3 入门教程 / 网络请求

Python3 入门教程

网络请求

本教程共 70 篇 · 第 53 篇 · 更新于 2026-07-22 · 约 5 分钟阅读

PythonPython3 入门教程网络请求requestsurllibHTTP

53. 网络请求

本节目标:学会用 urllib 发送基础 HTTP 请求,掌握 requests 库的高级用法,理解状态码、请求头和会话的概念。

现代程序很少孤立运行,几乎都要跟网络打交道:调用 API、下载文件、发送 webhook。Python 提供了标准库的 urllib 和第三方库 requests 两种方式来发送 HTTP 请求。

urllib:标准库方案

urllib 是 Python 内置的网络请求工具,不需要额外安装:

from urllib import request

# 最简单的 GET 请求
resp = request.urlopen('https://api.github.com')
print(resp.status)       # 200
print(resp.read().decode('utf-8'))

添加请求头

很多 API 要求提供 User-Agent 或其他头部:

from urllib import request

req = request.Request(
    'https://api.github.com',
    headers={'User-Agent': 'Mozilla/5.0'}
)
resp = request.urlopen(req)

发送 POST 请求

from urllib import request, parse

data = parse.urlencode({'name': 'Alice', 'age': '25'}).encode('utf-8')
req = request.Request('https://httpbin.org/post', data=data, method='POST')
resp = request.urlopen(req)
print(resp.read().decode('utf-8'))
Note

urllib 功能完整,但 API 设计偏底层。每次请求都要手动处理编码、头部、错误处理,代码比较啰嗦。日常开发中,大部分开发者会选择 requests

requests:更人性化的选择

requests 是 Python 社区最受欢迎的 HTTP 库,口号是「HTTP for Humans」。

安装:

pip install requests

基础请求

import requests

# GET
resp = requests.get('https://api.github.com')
print(resp.status_code)  # 200
print(resp.text)         # 响应文本
print(resp.json())       # 直接解析 JSON

# 带参数
resp = requests.get('https://httpbin.org/get', params={'key': 'value'})
print(resp.url)  # https://httpbin.org/get?key=value

# POST
resp = requests.post(
    'https://httpbin.org/post',
    data={'name': 'Alice'}
)
Tip

requests 会自动处理 URL 编码、JSON 解析、字符集检测。返回的 Response 对象封装了状态码、头部、内容等所有信息。

请求头和 JSON 数据

import requests

headers = {
    'User-Agent': 'MyApp/1.0',
    'Authorization': 'Bearer token123'
}

resp = requests.post(
    'https://api.example.com/users',
    headers=headers,
    json={'name': 'Alice', 'age': 25}  # 自动序列化为 JSON
)

print(resp.headers.get('Content-Type'))

上传文件

with open('photo.jpg', 'rb') as f:
    resp = requests.post(
        'https://httpbin.org/post',
        files={'file': f}
    )

超时设置

网络请求可能卡住,永远设置超时:

try:
    resp = requests.get('https://slow.site.com', timeout=5)
except requests.Timeout:
    print('请求超时')

timeout 参数可以是 (连接超时, 读取超时) 的元组,也可以是一个总秒数。

Warning

不写 timeout 的请求,在网络异常时可能挂起几十分钟。这是生产环境的大坑,务必养成设置超时的好习惯。

使用 Session

如果多个请求需要共享 cookie、头部或连接池,用 Session

import requests

session = requests.Session()
session.headers.update({'User-Agent': 'MyApp/1.0'})

# 登录后 cookie 自动保持
session.post('https://api.example.com/login', json={'user': 'alice'})

# 后续请求自动带上 cookie
resp = session.get('https://api.example.com/profile')

Session 还会复用底层 TCP 连接,发送多个请求到同一主机时性能更好。

状态码和异常处理

import requests

resp = requests.get('https://httpbin.org/status/404')
print(resp.status_code)  # 404

# 如果状态码 >= 400,抛 HTTPError
resp.raise_for_status()

常用状态码:

状态码含义
200成功
301/302重定向
400请求参数错误
401未授权
403禁止访问
404资源不存在
500服务器内部错误
502/503网关/服务不可用

实战:下载文件并显示进度

import requests

url = 'https://example.com/large.zip'
resp = requests.get(url, stream=True)
resp.raise_for_status()

total = int(resp.headers.get('content-length', 0))
downloaded = 0

with open('large.zip', 'wb') as f:
    for chunk in resp.iter_content(chunk_size=8192):
        f.write(chunk)
        downloaded += len(chunk)
        if total:
            percent = downloaded / total * 100
            print(f"\r下载进度: {percent:.1f}%", end='')

print("\n下载完成")

stream=True 让响应内容逐块读取,避免大文件一次性载入内存。iter_content() 返回指定大小的数据块。

urllib vs requests:怎么选

场景推荐
不能安装第三方依赖urllib
快速脚本、日常开发requests
需要异步/高性能aiohttp(第 63 章讲)

requests 的代码可读性和开发效率远超 urllib。除非有严格的依赖限制,否则优先用 requests

小结

  • urllib 是标准库,功能完整但 API 偏底层。
  • requests 更人性化,自动处理编码、JSON、cookie 等细节。
  • Session 共享状态和连接,适合多请求场景。
  • 所有网络请求都要设 timeout,防止无限挂起。
  • raise_for_status() 检查响应是否成功。

网络请求是程序跟外界通信的桥梁。写请求代码时,多考虑异常情况和超时处理,你的程序在弱网环境下会稳得多。


来源:参考了 runoob「Python3 urllib」和「Python requests」、liaoxuefeng「urllib」和「requests」等,改写后所得。