在爬虫实战里,遇到 HTTPS 站点是日常。HTTPS 本质上在传输层加密,但对爬虫影响主要落在证书验证、重定向、HTTP/2、SNI、压缩以及反爬策略上。本文面向工程实现,讲清用 Python 抓 HTTPS 的常见方案、实用代码、遇到证书/加密/反爬时的处理办法,以及如何用抓包工具定位问题(包含在移动端或真机场景下用 抓包大师 Sniffmaster 的补充方法)。
一、常见工具与选型
- requests:同步、易上手,适合普通页面与 API。
- aiohttp / httpx (async):并发抓取,高吞吐场景首选。
- Selenium / Playwright:渲染 JS、处理复杂交互与验证码。
- mitmproxy / Charles / Fiddler:抓包与调试 HTTPS 请求;mitmproxy 支持 Python 脚本化。
- tcpdump/Wireshark/Sniffmaster:遇到 TLS 握手失败或移动端问题时做底层/真机抓包。
二、基础代码示例(requests 与证书校验)
import requestsurl = "https://example.com/api"
s = requests.Session()
s.headers.update({"User-Agent": "Mozilla/5.0 (compatible)"})
resp = s.get(url, timeout=10) # 默认 verify=True,会校验证书
print(resp.status_code, resp.headers.get('content-type'))
如果遇到自签或测试证书,可指定 CA 文件:
resp = s.get(url, verify="/path/to/ca_bundle.pem")
切记:verify=False
可临时调试,但有安全风险,不应用于生产。
三、并发抓取(aiohttp 快速示例)
import asyncio, aiohttpasync def fetch(session, url):async with session.get(url, ssl=True) as r:return await r.text()async def main(urls):async with aiohttp.ClientSession() as session:tasks = [fetch(session, u) for u in urls]res = await asyncio.gather(*tasks)print(len(res))# asyncio.run(main(list_of_urls))
aiohttp 可以传入自定义 ssl
上下文以处理证书问题或 SNI。
四、常见 HTTPS 与抓取问题及对策
1) 证书验证失败(CERTIFICATE_VERIFY_FAILED
)
- 检查本机
certifi
是否最新;在受控测试环境使用自建 CA 并把 CA 导入系统/requests 的 CA bundle。 - 用
openssl s_client -connect host:443 -servername host
查看服务器证书链。
2) 重定向与 Cookie 签名
- 使用
Session()
保持 cookie。很多接口签名会把时间戳、nonce 与 cookie 联动,务必统一会话并重试策略。
3) 压缩/编码显示为乱码
- 检查
Content-Encoding
(gzip、br),requests/aiohttp 通常会自动解压;若返回二进制(protobuf/图片),用对应解析器处理。
4) HTTP/2 / TLS 特性
- requests 默认走 HTTP/1.1;若需 HTTP/2 可使用
httpx
或hyper
,部分站点仅在 HTTP/2 下才返回期望内容。
5) SNI 与多域名
- 使用支持 SNI 的 OpenSSL(大多现代 Python 都支持);若遇到证书与域名不一致,检查客户端请求中的
servername
。
五、应对反爬与抗封策略(工程化)
- Header 与 UA 升级:伪装常用浏览器 UA、Referer、Accept-Language。
- IP 轮换/代理池:短期用高匿名代理并控制速率;对于重要项目,使用付费代理并统计失效率。
- 请求速率与随机延迟:尊重 robots.txt、避免高并发短时突发。
- 浏览器行为模拟:用 Selenium/Playwright 渲染并执行 JS、触发浏览器指纹(但需控制并发与资源)。
- 验证码:优先避免触发,必要时结合人工/第三方识别服务。
- 签名逆向:如果接口有签名算法,逆向客户端 JS / APP 签名逻辑或使用同构环境复现签名(注意合规)。
六、抓包与调试 HTTPS 的实际流程
- 本地用
requests
发请求并复现问题。 - 用
mitmproxy
或 Charles 做代理抓包,观察请求头、TLS 握手、重定向与响应体。mitmproxy 支持写脚本修改请求并记录日志。 - 当代理看不到流量或 App/移动端行为异常,可能是 Pinning、mTLS 或 App 使用原始套接字:这时需要真机抓包或底层抓包。
- 桌面可用
tcpdump
+ Wireshark 分析 ClientHello/Alert。 - iOS/Android 真机场景,普通代理常被拒绝,这时可以使用 USB 直连抓包工具(例如 抓包大师 Sniffmaster)直接捕获设备流量、按 App 过滤并导出 PCAP,方便在 Wireshark 中进一步分析 TLS 握手与证书链问题。
- 桌面可用
七、mitmproxy 用于自动化调试(小示例)
# save as addon.py
from mitmproxy import httpdef response(flow: http.HTTPFlow):if "api.example.com" in flow.request.host:# 打印或修改响应,或记录原始 bodyprint(flow.response.status_code, len(flow.response.content))
运行:mitmproxy -s addon.py
,并在请求中指定代理。适合在爬虫开发时做断点调试或自动注入。
八、合规与风险提示
抓取数据前务必确认目标网站的使用条款与法律合规;在生产环境或客户数据上进行抓包/存储时要做好脱敏与权限控制。对付验证码或绕过认证时尤须慎重,优先寻求授权测试环境或 API 合作。
构建稳定的 Python HTTPS 爬虫需要把请求实现、证书与 TLS 兼容、反爬策略与抓包调试这几部分当成工程化流程来做。日常建议是:用 requests/aiohttp 做主抓取,用 mitmproxy/Charles 做抓包调试;当遇到移动端/真机或 Pinning/mTLS 难题时,把 Sniffmaster 作为排查链路的一部分,结合 Wireshark 做握手级别分析。把重试、代理池、限速、日志与监控整合后,爬虫稳定性会显著提升。