在网络爬虫、API调用、接口测试等场景中,发送HTTP请求是核心需求。Python的requests库以其简洁的API、强大的功能和人性化的设计,成为处理HTTP请求的首选工具------相比Python内置的urllib,它省去了繁琐的编码和解码步骤,让开发者能更专注于业务逻辑。本文将从基础用法→核心功能→实战案例→避坑指南 ,全方位带你掌握requests,轻松应对各类网络请求场景。
一、什么是requests?为什么选择它?
requests是Python的一个第三方HTTP库,由Kenneth Reitz开发,遵循"简单优雅"的设计哲学。它封装了底层的网络通信细节,提供了直观的API,让发送HTTP请求变得像调用函数一样简单。
为什么requests是处理HTTP的最佳选择?
- 简洁易用:一行代码即可发送GET/POST请求,无需手动处理URL编码、Cookie管理等细节;
- 功能全面:支持GET、POST、PUT、DELETE等所有HTTP方法,以及会话保持、文件上传、代理设置等高级功能;
- 自动处理细节:自动解析JSON响应、处理gzip压缩、管理连接池,减少开发者的重复劳动;
- 活跃的社区 :文档完善(官方文档),问题解决方案丰富,遇到问题能快速找到答案。
举个直观的例子:用urllib发送一个带参数的GET请求需要5行代码处理编码和请求,而用requests只需1行------这就是requests的魅力。
二、安装与导入:5分钟上手准备
1. 安装requests
requests不是Python标准库,需用pip安装:
bash
pip install requests # 基础安装,支持所有核心功能
2. 导入requests
使用时直接导入即可,无需复杂配置:
python
import requests # 导入库
三、核心功能:发送HTTP请求
HTTP请求的核心是"方法+URL+参数+头部信息",requests为每种HTTP方法都提供了对应的函数(如requests.get()、requests.post()),用法高度统一。
1. GET请求:获取资源(最常用)
GET请求用于从服务器获取资源(如网页内容、API数据),参数通常通过URL的查询字符串(?key=value&key2=value2)传递。
(1)基础GET请求
python
# 发送GET请求到百度首页
url = "https://www.baidu.com"
response = requests.get(url) # 返回一个Response对象
# 查看响应基本信息
print("状态码:", response.status_code) # 200表示成功
print("响应头部:", response.headers) # 字典形式的响应头
print("编码方式:", response.encoding) # 自动识别的编码(如'ISO-8859-1')
print("网页内容(前500字符):", response.text[:500]) # 文本形式的响应体
(2)带参数的GET请求
通过params参数传递查询字符串,无需手动拼接URL(requests会自动编码特殊字符):
python
# 示例:调用天气API(模拟,实际需替换为真实API)
url = "https://api.weather.com/query"
params = {
"city": "北京", # 城市名
"key": "abc123", # API密钥
"format": "json" # 返回格式
}
# 发送带参数的GET请求
response = requests.get(url, params=params)
# 查看实际请求的URL(自动拼接了参数)
print("实际请求URL:", response.url) # 输出:https://api.weather.com/query?city=北京&key=abc123&format=json
# 解析JSON响应(API通常返回JSON)
if response.status_code == 200: # 200表示请求成功
data = response.json() # 自动解析JSON,返回字典/列表
print("天气数据:", data)
else:
print(f"请求失败,状态码:{response.status_code}")
关键说明:
response.text:返回字符串形式的响应体(适用于HTML、纯文本);response.json():自动解析JSON格式的响应体(适用于API),若响应不是JSON会抛JSONDecodeError;response.content:返回字节形式的响应体(适用于图片、二进制文件)。
2. POST请求:提交数据
POST请求用于向服务器提交数据(如表单提交、API数据上传),数据通常放在请求体中(而非URL),更安全且支持更大的数据量。
(1)提交表单数据(application/x-www-form-urlencoded)
用data参数传递表单数据(字典形式):
python
# 示例:模拟登录表单提交(模拟URL,非真实接口)
url = "https://example.com/login"
data = {
"username": "test_user",
"password": "test_pass123",
"remember_me": "1"
}
# 发送POST请求,提交表单数据
response = requests.post(url, data=data)
print("登录响应:", response.text)
(2)提交JSON数据(application/json)
API接口通常要求提交JSON格式数据,用json参数直接传递Python字典(requests会自动序列化并设置Content-Type: application/json):
python
# 示例:调用创建用户的API(模拟)
url = "https://api.example.com/users"
user_data = {
"name": "张三",
"age": 25,
"email": "zhangsan@example.com"
}
# 发送POST请求,提交JSON数据
response = requests.post(url, json=user_data) # 自动处理JSON序列化
if response.status_code == 201: # 201表示资源创建成功
print("用户创建成功:", response.json())
else:
print("创建失败:", response.text)
3. 其他HTTP方法
requests支持所有HTTP标准方法,用法与GET/POST一致:
requests.put(url, data=...):更新资源(全量更新);requests.patch(url, data=...):部分更新资源;requests.delete(url):删除资源;requests.head(url):只获取响应头(无响应体);requests.options(url):获取服务器支持的HTTP方法。
示例:删除资源
python
url = "https://api.example.com/users/123"
response = requests.delete(url)
if response.status_code == 204: # 204表示删除成功(无响应体)
print("用户删除成功")
四、进阶功能:应对复杂场景
实际开发中,HTTP请求往往需要处理 headers、Cookies、代理等细节,requests提供了完善的支持。
1. 设置请求头(Headers)
服务器通常通过User-Agent识别客户端类型(如浏览器、爬虫),若不设置可能被拒绝访问(反爬机制)。用headers参数自定义请求头:
python
url = "https://www.example.com"
# 模拟浏览器请求头(从浏览器开发者工具中复制)
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36",
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
"Referer": "https://www.google.com/" # 防盗链:表示从谷歌跳转过来
}
response = requests.get(url, headers=headers)
print("响应状态码:", response.status_code) # 200表示成功(若不设headers可能返回403)
2. 处理Cookies
Cookies用于维持会话状态(如登录状态),requests会自动处理响应中的Cookies,并在后续请求中携带。
(1)自动管理Cookies
python
# 步骤1:登录(服务器返回Cookies)
login_url = "https://example.com/login"
data = {"username": "user", "password": "pass"}
response = requests.post(login_url, data=data)
# 步骤2:访问需要登录的页面(自动携带登录后的Cookies)
profile_url = "https://example.com/profile"
response = requests.get(profile_url) # 无需手动传递Cookies
print("个人信息页面:", response.text)
(2)手动设置Cookies
若需手动控制Cookies,可通过cookies参数传递字典:
python
url = "https://example.com"
cookies = {"user_id": "123", "session": "abcdef123456"}
response = requests.get(url, cookies=cookies)
3. 设置超时时间(Timeout)
若服务器无响应,程序会一直阻塞,用timeout参数设置超时时间(单位:秒):
python
url = "https://www.example.com"
try:
# 3秒内未收到响应则超时
response = requests.get(url, timeout=3)
print("请求成功")
except requests.exceptions.Timeout:
print("请求超时(3秒内未响应)")
except requests.exceptions.RequestException as e: # 捕获其他请求异常
print(f"请求失败:{e}")
4. 使用代理(Proxies)
爬取数据时,频繁请求可能导致IP被封,用代理IP隐藏真实IP:
python
url = "https://www.example.com"
# 代理配置(HTTP和HTTPS代理)
proxies = {
"http": "http://123.45.67.89:8080", # HTTP代理
"https": "https://123.45.67.89:8080" # HTTPS代理
}
# 发送带代理的请求
response = requests.get(url, proxies=proxies)
print("响应状态码:", response.status_code)
注意:实际使用需替换为有效的代理IP(可从代理服务商获取)。
5. 会话保持(Session)
requests.Session()创建会话对象,能在多个请求间保持Cookies、headers等状态,适合需要连续操作的场景(如登录→浏览→下单):
python
# 创建会话对象
session = requests.Session()
# 1. 登录(会话会保存Cookies)
login_url = "https://example.com/login"
session.post(login_url, data={"username": "user", "password": "pass"})
# 2. 访问个人中心(自动携带登录Cookies)
profile_url = "https://example.com/profile"
response = session.get(profile_url)
print("个人中心内容:", response.text)
# 3. 退出登录
logout_url = "https://example.com/logout"
session.get(logout_url)
# 关闭会话(可选)
session.close()
6. 文件上传
用files参数上传文件(适用于multipart/form-data类型的表单):
python
url = "https://example.com/upload"
# 准备上传的文件(打开文件时用二进制模式"rb")
files = {
"file": open("test.jpg", "rb"), # "file"是表单字段名
"description": ("", "这是一张测试图片", "text/plain") # 额外的文本字段
}
response = requests.post(url, files=files)
print("上传结果:", response.text)
# 记得关闭文件(或用with语句)
files["file"].close()
五、实战案例:爬取豆瓣电影TOP250
用requests爬取豆瓣电影TOP250的名称、评分和引言,展示完整的网络请求+数据提取流程(需配合简单的字符串处理,实际爬虫可结合BeautifulSoup解析HTML)。
python
import requests
import re # 用正则提取数据(简化示例,实际推荐BeautifulSoup)
# 豆瓣电影TOP250第一页URL
url = "https://movie.douban.com/top250"
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36"
}
try:
# 发送请求
response = requests.get(url, headers=headers, timeout=5)
response.raise_for_status() # 若状态码不是200,抛HTTPError
response.encoding = "utf-8" # 手动指定编码(解决部分网站乱码)
# 用正则提取电影信息(简化示例)
# 匹配电影名称:<span class="title">肖申克的救赎</span>
titles = re.findall(r'<span class="title">([^&]*?)</span>', response.text)
# 匹配评分:<span class="rating_num" property="v:average">9.7</span>
ratings = re.findall(r'<span class="rating_num" property="v:average">([0-9.]+)</span>', response.text)
# 匹配引言:<span class="inq">希望让人自由。</span>
quotes = re.findall(r'<span class="inq">(.*?)</span>', response.text)
# 打印结果(前5部)
print("豆瓣电影TOP250(前5部):")
for i in range(5):
print(f"{i+1}. 电影名:{titles[i]},评分:{ratings[i]},引言:{quotes[i]}")
except requests.exceptions.HTTPError as e:
print(f"HTTP错误:{e}")
except requests.exceptions.RequestException as e:
print(f"请求失败:{e}")
输出结果:
豆瓣电影TOP250(前5部):
1. 电影名:肖申克的救赎,评分:9.7,引言:希望让人自由。
2. 电影名:霸王别姬,评分:9.6,引言:风华绝代。
3. 电影名:阿甘正传,评分:9.5,引言:一部美国近现代史。
4. 电影名:泰坦尼克号,评分:9.4,引言:失去的才是永恒的。
5. 电影名:这个杀手不太冷,评分:9.4,引言:怪蜀黍和小萝莉 的纯粹爱情。
六、避坑指南:requests常见错误及解决
1. 中文乱码问题
问题 :response.text返回的内容中文乱码。
原因 :requests自动识别的编码(response.encoding)与网页实际编码不一致。
解决 :手动指定正确编码(如utf-8、gbk):
python
response = requests.get(url)
response.encoding = "utf-8" # 强制设置编码为utf-8
print(response.text)
2. 被反爬机制拦截(403 Forbidden)
问题 :请求返回403,提示"拒绝访问"。
原因 :服务器识别出爬虫(如缺少User-Agent、请求频率过高)。
解决:
- 设置真实的
User-Agent(模拟浏览器); - 降低请求频率(加
time.sleep(1)); - 使用代理IP;
- 携带
Referer头(模拟从合法页面跳转)。
3. JSON解析失败(JSONDecodeError)
问题 :response.json()抛JSONDecodeError。
原因 :响应内容不是JSON格式(如HTML、错误信息)。
解决 :先检查状态码,非200时用response.text查看错误信息:
python
response = requests.get(url)
if response.status_code == 200:
try:
data = response.json()
except json.JSONDecodeError:
print("响应不是JSON:", response.text)
else:
print("请求失败:", response.text)
4. 大文件下载内存溢出
问题 :下载大文件(如1GB视频)时,response.content会将整个文件加载到内存,导致溢出。
解决 :用stream=True流式下载,分块写入磁盘:
python
url = "https://example.com/large_file.zip"
with requests.get(url, stream=True) as response:
with open("file.zip", "wb") as f:
for chunk in response.iter_content(chunk_size=1024*1024): # 每次1MB
if chunk: # 过滤空块
f.write(chunk)
print("下载完成")
5. 忽略SSL证书验证错误
问题 :访问HTTPS网站时,因证书无效抛SSLError。
解决 :开发环境可临时设置verify=False(生产环境不推荐,有安全风险):
python
response = requests.get("https://self-signed.example.com", verify=False)
七、总结:requests是网络请求的最佳拍档
requests的核心价值在于 "化繁为简" ------它将复杂的HTTP协议细节封装成直观的API,让开发者无需关注底层实现,只需专注于"发送什么请求"和"如何处理响应"。无论是简单的网页爬取、API调用,还是复杂的会话管理、文件上传,requests都能轻松应对。
学习建议:
- 熟练掌握基础方法 :GET/POST是核心,务必理解
params、data、json参数的区别; - 重视异常处理 :网络请求充满不确定性,用
try-except捕获RequestException及子类异常; - 模拟浏览器行为:处理反爬时,学会复制真实请求的headers、Cookies;
- 结合解析库使用 :爬取网页时,
requests配合BeautifulSoup(解析HTML)或lxml(高效解析),能大幅提升效率; - 查阅官方文档 :
requests功能丰富,官方文档是最好的学习资料。
掌握requests后,你会发现网络请求不再是难题------从调用开放API获取数据,到开发简单的爬虫收集信息,再到测试自己的后端接口,它都能成为你的得力助手。