Python入门第11课:Python网络请求入门,使用requests库轻松获取网页数据
Python入门第11课:Python网络请求入门,使用requests库轻松获取网页数据
作者: 蛋皮
标签: Python, requests, 网络请求, HTTP, Web Scraping, API, 数据获取
欢迎回到Python入门系列!在前两节课中,我们学习了面向对象编程的精髓,并掌握了操作Excel文件的强大技巧。今天,我们将开启Python在互联网世界的大门——网络请求。
想象一下,你的Python程序不仅能处理本地文件,还能主动与全球数以亿计的网站和服务器对话,获取最新的新闻、天气、股票信息,或是调用各种强大的在线服务(API)。这不再是科幻,而是通过Python的requests
库可以轻松实现的现实。
requests
库被誉为“Python的HTTP库”,它以其简洁、优雅的API设计,让发送HTTP请求变得像说话一样简单。无论你是想抓取网页内容、与Web API交互,还是自动化测试,requests
都是你的首选工具。
为什么选择 requests
?
在requests
出现之前,Python标准库中的urllib
也能发送网络请求,但其API相对复杂繁琐。requests
库的出现彻底改变了这一局面,它提供了:
- 简洁的API: 一行代码即可发送GET/POST请求。
- 人性化的会话 (Sessions): 轻松管理Cookie和持久连接。
- 自动处理编码: 自动解码响应内容。
- 强大的功能: 支持文件上传、SSL验证、代理、超时设置、身份验证等。
- 社区支持: 拥有庞大的用户群和丰富的文档。
一句话:requests
让你用最少的代码,做最多的网络交互。
准备工作:安装 requests
在开始之前,请确保已安装requests
库。打开命令行(终端),执行:
pip install requests
安装完成后,就可以在Python脚本中导入使用了:
import requests
核心:HTTP请求与响应
在深入requests
之前,我们需要了解最基本的网络通信协议——HTTP (HyperText Transfer Protocol)。
- 客户端 (Client): 你的Python程序就是客户端,它向服务器发出请求 (Request)。
- 服务器 (Server): 网站或API的计算机,它接收请求并返回响应 (Response)。
- 请求方法 (HTTP Methods): 最常见的两种:
- GET: 用于获取资源(如网页内容、API数据)。这是最常用的。
- POST: 用于向服务器提交数据(如表单提交、上传文件)。
- 状态码 (Status Code): 服务器在响应中返回一个三位数的状态码,表示请求的结果:
200 OK
: 请求成功!404 Not Found
: 请求的资源不存在。500 Internal Server Error
: 服务器内部错误。403 Forbidden
: 禁止访问。401 Unauthorized
: 未授权。
requests
库的核心就是发送这些HTTP请求,并处理返回的响应。
发送GET请求:获取网页或API数据
GET请求是最基础、最常用的请求类型。
1. 最简单的GET请求
import requests# 发送一个GET请求到指定URL
response = requests.get('https://httpbin.org/get')# 检查请求是否成功
if response.status_code == 200:print("请求成功!")# 获取响应的文本内容print(response.text)
else:print(f"请求失败,状态码: {response.status_code}")
代码解析:
requests.get(url)
: 发送一个GET请求到url
,返回一个Response
对象。response.status_code
: 获取HTTP状态码。response.text
: 获取响应的文本内容(字符串形式)。
2. 处理JSON响应 (API常用)
许多API返回的数据格式是JSON。requests
可以轻松处理它。
import requests# 一个返回JSON的公共测试API
response = requests.get('https://jsonplaceholder.typicode.com/posts/1')if response.status_code == 200:# 直接将响应的JSON内容解析为Python字典data = response.json()print("获取到的JSON数据:")print(data)# 现在可以像操作普通字典一样操作dataprint(f"文章标题: {data['title']}")print(f"用户ID: {data['userId']}")
else:print(f"请求失败: {response.status_code}")
关键点: response.json()
方法会自动将JSON字符串解析成Python的dict
或list
。
3. 添加查询参数 (Query Parameters)
URL中的?
后面的部分就是查询参数,常用于搜索、分页等。
import requests# 方法1: 手动拼接URL (不推荐,容易出错)
# response = requests.get('https://httpbin.org/get?name=张三&age=25')# 方法2: 使用 params 参数 (推荐!)
params = {'name': '张三','age': 25,'city': '北京'
}
response = requests.get('https://httpbin.org/get', params=params)# 打印最终的URL,看看params是如何被拼接的
print(f"请求的URL: {response.url}")
# 输出: https://httpbin.org/get?name=%E5%BC%A0%E4%B8%89&age=25&city=%E5%8C%97%E4%BA%AC
# (中文被URL编码了)if response.status_code == 200:data = response.json()# httpbin.org会把收到的参数回显在响应中print("服务器收到的参数:", data['args'])
4. 设置请求头 (Headers)
请求头 (Headers) 包含了关于客户端的额外信息,如浏览器类型、接受的内容类型、身份令牌等。有些网站会检查User-Agent
来判断是否是爬虫。
import requestsurl = 'https://httpbin.org/headers'# 定义自定义请求头
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36','Accept': 'application/json', # 告诉服务器我们希望接收JSON'Authorization': 'Bearer your-token-here' # 如果API需要身份验证
}response = requests.get(url, headers=headers)if response.status_code == 200:data = response.json()print("服务器看到的请求头:")print(data['headers'])# 会看到我们设置的User-Agent, Accept等
else:print(f"请求失败: {response.status_code}")
发送POST请求:提交数据
POST请求用于向服务器发送数据。
1. 提交表单数据 (Form Data)
import requestsurl = 'https://httpbin.org/post'
data = {'username': 'alice','password': 'secret123'
}# 使用 data 参数发送表单数据 (application/x-www-form-urlencoded)
response = requests.post(url, data=data)if response.status_code == 200:result = response.json()print("服务器收到的表单数据:")print(result['form']) # httpbin.org会把收到的表单数据放在form字段
else:print(f"POST请求失败: {response.status_code}")
2. 发送JSON数据
import requestsurl = 'https://httpbin.org/post'
json_data = {'name': 'Bob','email': 'bob@example.com','active': True
}# 使用 json 参数发送JSON数据 (会自动设置Content-Type为application/json)
response = requests.post(url, json=json_data) # 注意是 json=json_dataif response.status_code == 200:result = response.json()print("服务器收到的JSON数据:")print(result['json']) # httpbin.org会把收到的JSON数据放在json字段
else:print(f"POST请求失败: {response.status_code}")
3. 上传文件
import requestsurl = 'https://httpbin.org/post'# 准备要上传的文件
files = {'file': open('example.txt', 'rb')} # rb: 二进制读取模式try:response = requests.post(url, files=files)if response.status_code == 200:result = response.json()print("文件上传成功!服务器收到的文件信息:")print(result['files'])else:print(f"文件上传失败: {response.status_code}")
finally:# 记得关闭文件files['file'].close()
实用技巧与高级功能
1. 设置超时 (Timeout)
防止请求因网络问题无限期挂起。
import requests
from requests.exceptions import Timeouttry:# 设置连接超时5秒,读取超时10秒response = requests.get('https://httpbin.org/delay/2', timeout=(5, 10))print("请求成功:", response.status_code)
except Timeout:print("请求超时了!")
2. 使用会话 (Session) 管理状态
当你需要与同一个服务器进行多次交互(如登录后访问其他页面),使用Session
对象可以自动管理Cookie,非常方便。
import requests# 创建一个会话对象
session = requests.Session()# 设置会话级别的默认头
session.headers.update({'User-Agent': 'MyApp/1.0'})# 模拟登录 (假设这个POST请求会返回一个包含登录状态的Cookie)
login_data = {'username': 'user', 'password': 'pass'}
login_response = session.post('https://httpbin.org/post', data=login_data)# 现在,后续的所有请求都会自动带上登录请求返回的Cookie
# 即使没有显式传递,session也会维护这个会话状态
profile_response = session.get('https://httpbin.org/cookies')
# profile_response会包含之前登录设置的Cookie# 使用完记得关闭会话
session.close()
3. 处理异常
网络请求可能因各种原因失败(网络断开、DNS错误、超时、服务器错误等)。使用try-except
块捕获异常是良好实践。
import requests
from requests.exceptions import RequestException, ConnectionError, HTTPErrorurl = 'https://httpbin.org/status/418' # 这个URL会返回418状态码 (I'm a teapot)try:response = requests.get(url, timeout=5)# 检查HTTP错误状态码response.raise_for_status() # 如果状态码>=400,会抛出HTTPError异常print("请求成功:", response.text)
except ConnectionError:print("连接错误:无法连接到服务器。")
except Timeout:print("请求超时。")
except HTTPError as e:print(f"HTTP错误: {e}")
except RequestException as e:print(f"请求发生未知错误: {e}")
4. 代理 (Proxy)
在某些网络环境下,可能需要通过代理服务器访问外部网络。
import requestsproxies = {'http': 'http://10.10.1.10:3128','https': 'http://10.10.1.10:1080'
}response = requests.get('https://httpbin.org/get', proxies=proxies)
一个实用的例子:获取天气信息
让我们结合所学,写一个简单的脚本,从一个公共天气API获取城市天气。
import requestsdef get_weather(city):"""从OpenWeatherMap API获取指定城市的天气信息。注意:你需要注册获取自己的API密钥 (APPID)。这里使用的是一个公共测试密钥,可能有限制。"""# 公共测试密钥 (请勿在生产环境使用,注册获取自己的)API_KEY = "45a724b567e3415e93e151307241808" # 这是一个示例,请替换为有效密钥BASE_URL = "http://api.weatherapi.com/v1/current.json"params = {'key': API_KEY,'q': city,'lang': 'zh' # 中文}try:response = requests.get(BASE_URL, params=params, timeout=10)response.raise_for_status() # 检查HTTP错误data = response.json()current = data['current']location = data['location']print(f"\n📍 城市: {location['name']}, {location['country']}")print(f"🌤 天气: {current['condition']['text']}")print(f"🌡 温度: {current['temp_c']}°C (体感 {current['feelslike_c']}°C)")print(f"💧 湿度: {current['humidity']}%")print(f"🌬 风速: {current['wind_kph']} km/h")except requests.exceptions.HTTPError as e:if response.status_code == 400:print(f"错误:城市 '{city}' 未找到或查询参数无效。")else:print(f"HTTP错误: {e}")except requests.exceptions.RequestException as e:print(f"网络请求错误: {e}")except KeyError as e:print(f"解析数据时出错,缺少关键字段: {e}")except Exception as e:print(f"发生未知错误: {e}")# 使用函数
get_weather("Beijing")
get_weather("Shanghai")
get_weather("New York")
注意: 上面的API密钥是示例,实际使用时需要去 WeatherAPI 注册并获取自己的免费密钥。
最佳实践与总结
- 总是检查状态码: 在使用响应内容前,务必检查
response.status_code
或使用response.raise_for_status()
。 - 设置超时: 避免程序因网络问题卡死。
- 处理异常: 使用
try-except
捕获网络请求中可能发生的各种异常。 - 尊重网站规则: 如果进行网页抓取(Web Scraping),请检查网站的
robots.txt
文件(如https://example.com/robots.txt
)和使用条款,避免过于频繁的请求(设置延迟),不要给服务器造成过大负担。 - 使用会话: 对于需要保持登录状态的多步操作,使用
requests.Session()
。 - 安全处理敏感信息: API密钥、密码等敏感信息不要硬编码在代码中,可以使用环境变量或配置文件。
- 选择合适的库:
requests
适用于同步请求。如果你需要处理成千上万的并发请求,可以考虑aiohttp
(异步) 或httpx
(支持同步和异步)。
总结
通过本课的学习,你已经掌握了使用requests
库进行网络请求的核心技能。你学会了:
- 发送 GET 和 POST 请求。
- 处理 JSON 响应和表单数据。
- 设置 请求头、查询参数 和 超时。
- 使用 Session 管理会话状态。
- 正确处理 异常。
requests
库打开了Python与互联网世界沟通的大门。无论是获取公开数据、调用第三方API,还是进行自动化测试,它都是你不可或缺的工具。
练习建议:
- 使用
requests
获取一个你喜欢的新闻网站的首页HTML,尝试用print(response.text)
查看内容。 - 找一个公共API(如GitHub API, JSONPlaceholder),练习发送GET和POST请求。
- 修改上面的天气脚本,让它能接受用户输入的城市名。
- 尝试使用
Session
模拟一个简单的登录流程(可以使用httpbin.org
的相关接口测试)。