跳转至

Python requests:可靠地获取网页

requests 用于发送 HTTP 请求。爬虫初学阶段最重要的不是“请求成功一次”,而是把超时、状态码、异常和编码处理清楚。下面只讨论获取公开页面的 GET 请求。

1. 安装与第一个请求

python -m pip install requests
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 默认不会超时,网络异常时程序可能无限等待。建议每个生产或学习脚本中的请求都显式设置超时:

requests.get("https://example.com/", timeout=10)

这里的 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,统一捕获后再转换为业务异常更容易处理。

调用示例:

html = fetch_html(
    "https://example.com/search",
    params={"q": "python", "page": 1},
)

最终 URL 会由库正确编码。值为 None 的查询参数不会被加入 URL。

4. textcontent 与编码

  • 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、系统证书或站点配置是否正确。

参考

评论