4. Python Requests库实战:从安装到Cookie管理
说实话,Python做网络请求,Requests库几乎是绕不开的选择。我最早用urllib的时候,那叫一个痛苦——手动拼接参数、处理编码、管理Cookie,写出来的代码又臭又长。后来换了Requests,感觉整个世界都清爽了。
这一章,咱们就把Requests库的核心用法过一遍。从安装开始,到GET/POST请求、参数处理、响应解析,最后聊到会话和Cookie管理。嗯,都是实战里天天用的东西。
4.1 安装与导入
安装很简单,一行命令搞定:
pip install requests
我个人习惯在虚拟环境里装,避免污染全局Python。如果你用的是Anaconda,也可以:
conda install requests
装完之后,导入就一句话:
import requests
这就够了。我见过有人写 from requests import *,其实没必要,保持命名空间干净比较好。
HTTP_PROXY 和 HTTPS_PROXY,不用额外设置。
4.2 发送GET请求
GET请求是最常见的。说白了,就是从服务器拿数据。比如我们抓取一个网页:
import requests
url = "https://api.github.com/users/octocat"
response = requests.get(url)
print(response.status_code) # 200
print(response.text) # 响应内容(字符串形式)
你看,就这么几行。我曾经在项目里用这个接口抓GitHub用户信息,结果忘了处理超时,程序卡了半小时。所以,我建议你加上超时参数:
response = requests.get(url, timeout=5) # 5秒超时
4.3 发送POST请求
POST请求通常用来提交数据。比如登录、提交表单。用法和GET差不多,只是多了一个 data 参数:
url = "https://httpbin.org/post"
payload = {"username": "admin", "password": "123456"}
response = requests.post(url, data=payload)
print(response.json()) # 解析JSON响应
为什么会用 data 而不是 params?因为POST的数据是放在请求体里的,不是URL上。你想想看,如果密码明文出现在URL里,那多危险。
如果服务器要求JSON格式,那就用 json 参数:
response = requests.post(url, json=payload)
Requests会自动帮你设置 Content-Type: application/json。这个细节,我当年踩过坑——手动设header,结果格式不对,服务器一直返回400。
4.4 处理请求参数
参数处理分两种:URL查询参数和请求体参数。
4.4.1 URL查询参数(GET)
用 params 参数,Requests会自动拼接到URL后面:
url = "https://api.github.com/search/repositories"
params = {"q": "requests", "sort": "stars"}
response = requests.get(url, params=params)
print(response.url) # 实际请求的URL
输出结果:
https://api.github.com/search/repositories?q=requests&sort=stars
你看,省去了手动拼接的麻烦。而且Requests会自动处理特殊字符的编码,比如中文、空格什么的。
4.4.2 请求体参数(POST)
前面已经演示过了,用 data 或 json。这里补充一个场景:文件上传。
files = {"file": open("data.csv", "rb")}
response = requests.post(url, files=files)
我在做数据采集时,经常需要上传文件到服务器做批处理。用 files 参数,Requests会自动设置 multipart/form-data 编码。
4.5 处理响应内容
拿到响应之后,怎么提取数据?这是关键。
| 属性/方法 | 说明 | 示例 |
|---|---|---|
response.text |
字符串形式响应(自动解码) | print(r.text) |
response.content |
字节形式响应(二进制数据) | r.content.decode('utf-8') |
response.json() |
解析为Python字典/列表 | data = r.json() |
response.status_code |
HTTP状态码 | if r.status_code == 200 |
response.headers |
响应头(字典形式) | r.headers['Content-Type'] |
response.encoding |
编码方式 | r.encoding = 'utf-8' |
我常用的套路是:先检查状态码,再解析JSON。如果状态码不是200,说明请求有问题,直接抛异常:
response.raise_for_status() # 状态码不是200时抛出HTTPError
嗯,这个 raise_for_status() 是我最喜欢的函数之一。省去了手动判断的麻烦。
4.6 会话与Cookie管理
很多网站需要登录才能访问数据。这时候就需要管理Cookie了。Requests提供了 Session 对象,可以自动保持Cookie。
4.6.1 使用Session
session = requests.Session()
# 第一次请求:登录
login_url = "https://example.com/login"
login_data = {"username": "user", "password": "pass"}
session.post(login_url, data=login_data)
# 第二次请求:访问需要登录的页面
profile_url = "https://example.com/profile"
response = session.get(profile_url)
print(response.text) # 已经携带了Cookie
你看,用Session之后,Cookie自动带上去了。不用手动去取Cookie再塞到Header里。我曾经在项目里手动管理Cookie,结果因为过期时间没处理好,数据采集到一半全失败了。后来改用Session,再没出过问题。
4.6.2 手动设置Cookie
有时候你需要从别的地方拿到Cookie,手动设置进去:
cookies = {"session_id": "abc123", "token": "xyz789"}
response = requests.get(url, cookies=cookies)
或者用 requests.utils.cookiejar_from_dict 转换:
from requests.utils import cookiejar_from_dict
jar = cookiejar_from_dict({"key": "value"})
response = requests.get(url, cookies=jar)
4.6.3 查看响应中的Cookie
response = requests.get(url)
print(response.cookies) # RequestsCookieJar对象
print(dict(response.cookies)) # 转为字典
这个在调试时很有用。你可以看看服务器返回了什么Cookie,是不是你想要的。
4.7 本章知识体系
下面这张图,帮你梳理Requests库的核心脉络:
这张图把Requests库的核心功能串起来了。你从安装开始,到发送请求、处理参数、解析响应,最后管理会话和Cookie。每一步都是数据采集的必备技能。