辛辛苦苦写了个爬虫本地跑得飞起一上量就“咔咔”报超时。赶紧找免费代理换上结果请求要么慢得像蜗牛要么直接返回一堆ProxyError心态原地爆炸。其实代理的配置远不止往proxies参数里塞个字典那么简单。今天咱们就把这事儿彻底聊透。‍我是爱折腾的一名程序媛喜欢研究全栈开发的各种实践热爱分享踩坑后的收获与思考也享受用代码写出各种实用小工具解决问题的快乐。如果你也在技术这条路上向前走关注我愿我们能彼此陪伴一起成为更好的自己 这篇文章能帮你解决什么带你分清楚http、https和socks代理分别该填在哪儿什么时候用。更重要的是给你一套能直接用的遍历代理列表防封策略并避开那些一踩一个准的坑。️ 主要内容脉络 代理的“双通道”到底怎么回事 http、https、socks 代理实战案例 如何遍历代理列表才真正有效 血泪换来的常见问题与解决方案 代理的双通道九成人一开始都搞混你向http://example.com发请求时可以走 HTTP 代理向https://example.com发请求时可以走 HTTPS 代理。但 requests 库里的写法容易让人恍惚。proxies {http: http://127.0.0.1:8080,https: http://127.0.0.1:8080,}看到没https这个键对应的值依然以http://开头。要注意这里填的是代理服务本身的协议不是你要请求的目标网站协议。你的代理服务器是 HTTP 服务无论转发的是 HTTP 还是 HTTPS 流量都要写http://。不过如果你用的是支持 HTTPS 的加密代理就可以填https://这样你和代理之间的连接也会被加密多一层保护。⚙️ 三种代理怎么用才对 HTTP 代理最基础只转发 HTTP 请求。适合爬取纯 HTTP 站点或者内网穿透。import requestsproxies {http: http://user:passproxy_ip:port,}resp requests.get(http://httpbin.org/ip, proxiesproxies, timeout10)print(resp.text) HTTPS 代理你可能会问刚才不是说https键值可以填http://吗是的但这里如果填https://意味着你与代理之间是 TLS 加密隧道别人抓包也看不到你在请求什么。对安全要求高的场景才用。proxies {https: https://secure_proxy:port,}resp requests.get(https://httpbin.org/ip, proxiesproxies, timeout10) SOCKS 代理这玩意儿更底层SOCKS工作在传输层它就是个“管道工”才不管你管道里流的是水HTTP还是天然气FTP。SOCKS代理分为两种版本SOCKS4和SOCKS5。SOCKS4仅支持TCP协议而SOCKS5不仅支持TCP还支持UDP协议并提供身份验证机制和服务器端域名解析等功能。Python 想用它得先装pip install requests[socks]proxies {http: socks5://127.0.0.1:1080,https: socks5://127.0.0.1:1080,}resp requests.get(https://api.github.com, proxiesproxies, timeout10)这里有个我亲自撞过的墙requests 的 socks 支持不是内置的忘了装PySocks就会抛出Missing dependencies for SOCKS support别问我怎么知道的。 代理列表怎么遍历才高效是不是以为直接写个for循环拿一个用报错就换下一个就完事了没那么简单。先校验可用性免费代理的死亡率极高拿来就用只会浪费时间。用之前先拿一个稳定的网站比如百度做一次超短超时的探测超时 3 秒直接跳过。标记失败次数每个代理连续失败 3 次就打入“冷宫”不要无限重试否则整个程序会被拖死。随机轮换而不是顺序取顺序取会让目标服务器看到规律反而容易触发封禁。用random.shuffle()打乱顺序每次请求前从池子里随机摸一个。给你看一个我一直在用的骨架import random, requestsproxy_pool [http://1.1.1.1:8080,socks5://2.2.2.2:1080,http://user:pass3.3.3.3:3128,]def get_random_proxy():return random.choice(proxy_pool)for url in urls:for _ in range(3): # 最多换3次代理proxy get_random_proxy()try:resp requests.get(url,proxies{http: proxy, https: proxy},timeout5)if resp.status_code 200:# 正常处理返回信息breakexcept:continueelse:print(f{url} 请求失败已穷尽代理)这里有一个很容易翻车的点千万不要在遍历中把失效代理从列表里remove多线程下会引发索引错误。改成把坏代理丢进一个set做黑名单过滤就好。# 全局黑名单线程安全起见可以用 set 配合锁或者直接用 queuebad_proxies set()def get_random_proxy():# 过滤掉黑名单里的代理good [p for p in proxy_pool if p not in bad_proxies]if not good:raise Exception(所有代理都已失效)return random.choice(good)def mark_bad_proxy(proxy):bad_proxies.add(proxy) # 只往 set 里加永远不删原列表使用时一旦请求失败就把代理丢进黑名单proxy get_random_proxy()try:resp requests.get(url, proxies{http: proxy, https: proxy}, timeout5)if resp.status_code ! 200:mark_bad_proxy(proxy)except:mark_bad_proxy(proxy)⚠️ 常见踩坑与急救包代理配了但感觉没走检查环境变量HTTP_PROXY、HTTPS_PROXY是否被预先设置。requests 会自动读它们而且优先级可能比你传入的proxies还高。我的习惯是直接用proxies参数显式传入并在脚本开头强制os.environ.pop(HTTP_PROXY, None)干净利落。用了代理后 SSL 证书报错