Python requests:可靠地获取网页
requests 用于发送 HTTP 请求。爬虫初学阶段最重要的不是“请求成功一次”,而是把超时、状态码、异常和编码处理清楚。下面只讨论获取公开页面的 GET 请求。
1. 安装与第一个请求
import requests
response = requests.get("https://example.com/", timeout=10)
response.raise_for_status()
print(response.status_code)
print(response.text[:100])
raise_for_status() 会在响应状态码表示客户端或服务端错误时抛出 HTTPError。因此不要只看“有没有返回内容”,应先确认请求是否成功。
2. 为什么必须设置 timeout
如果不传 timeout,Requests 默认不会超时,网络异常时程序可能无限等待。建议每个生产或学习脚本中的请求都显式设置超时:
这里的 10 不是“整个下载最多 10 秒”。它表示底层 socket 连续 10 秒没有收到数据时抛出超时异常。对于大文件、慢速响应或更复杂的连接/读取控制,需要根据任务进一步设计。
3. 一个可复用的获取函数
from typing import Any
import requests
def fetch_html(url: str, params: dict[str, Any] | None = None) -> str:
headers = {
"User-Agent": "MyLearningBot/0.1 (contact: your-email@example.com)"
}
try:
response = requests.get(
url,
params=params,
headers=headers,
timeout=10,
)
response.raise_for_status()
except requests.exceptions.RequestException as error:
raise RuntimeError(f"请求失败:{url}") from error
return response.text
这个函数有四个关键点:
params让 Requests 负责 URL 查询参数的编码,避免手工拼接字符串。User-Agent说明请求来自什么程序;应使用真实、可联系的信息。timeout防止无期限等待。- 所有 Requests 主动抛出的异常都继承自
RequestException,统一捕获后再转换为业务异常更容易处理。
调用示例:
最终 URL 会由库正确编码。值为 None 的查询参数不会被加入 URL。
4. text、content 与编码
response.text:Requests 根据响应头推测编码后解码得到的字符串,适合多数 HTML 文本。response.content:未经文本解码的字节数据,适合下载二进制文件,或需要自行判断编码时使用。
如果页面文字乱码,不要直接猜测一种编码覆盖。先检查响应头、页面声明和实际字节;确认后才设置 response.encoding。对于 HTML 解析,通常把确认编码后的 response.text 传给解析器即可。
5. 不建议的写法
# 不推荐:没有超时,也没有状态码检查
html = requests.get(url).text
# 不推荐:关闭 TLS 证书校验
html = requests.get(url, verify=False).text
verify=False 会削弱 HTTPS 的安全性,不应用它来“解决”证书报错。应先确认 URL、系统证书或站点配置是否正确。