)
玩爬虫这么久我踩过最多的坑不是解析难、不是异步慢而是IP 被疯狂封禁。真的太烦了本地IP跑一会儿就403、访问超时、直接拉黑爬虫动不动就罢工每次都得停手换网络。后面我干脆自己手写了一套轻量代理IP轮换池不用 Redis、不用复杂框架纯原生 Requests 就能跑。自动换IP、自动剔除坏IP、失败自动重试算是彻底解决了普通爬虫被封IP的问题。今天把我自己日常在用的这套完整方案分享出来新手直接复制就能跑不用瞎折腾。先说说我们为什么一定要用代理池其实道理特别简单你一直用同一个IP高频请求网站服务器一眼就能识别出你是爬虫直接风控、封禁。代理池的作用就是每次请求换个新IP伪装成不同的普通用户在访问网站根本抓不到你的真实地址被封概率直接降到很低。我这套代码主打一个轻量、省心、全自动不用手动管IP失效、不用自己切换全部程序自动处理。环境超级简单全程只需要一个依赖就是 requests直接装就行pip install requests代理IP这块我说句实话新手练习随便找免费代理就行够用但如果是长期跑项目、正式爬数据一定要用付费代理。免费代理通病就是寿命短、延迟高只适合练手学习。我理解的代理池核心逻辑通俗版我自己写代码的时候就遵循四个核心步骤特别好理解1.捞IP从代理接口批量拿一堆代理IP出来2.筛IP逐个测试把超时、连不上的坏IP全部删掉3.存IP把能用的优质IP存在列表里备用4.自动换IP每次发请求随机挑一个坏了自动丢、空了自动更新整套流程全自动完全不用人工干预。直接上我日常在用的完整源码这是我精简优化后的版本容错、重试、删坏IP、自动更新全部写好了注释我也写得很直白大家直接照搬运行就行。import requests import random import time class ProxyPool: def __init__(self): # 存放可用代理IP self.proxy_list [] # 用来测试代理是否正常的公共接口 self.test_url http://httpbin.org/ip # 超时5秒直接判定失效 self.timeout 5 # 最多重试3次 self.max_retry 3 def get_free_proxies(self): 获取代理站大爷API proxy_api https://www.zdaye.com/get try: res requests.get(proxy_api, timeout10) if res.status_code 200: proxy_data res.json() return proxy_data.get(proxy_list, []) except Exception as e: print(暂时获取不到新代理IP) return [] def check_proxy(self, proxy): 检测单个代理是否能用 try: proxies { http: fhttp://{proxy}, https: fhttp://{proxy} } res requests.get(self.test_url, proxiesproxies, timeoutself.timeout) if res.status_code 200: print(f可用代理{proxy}) return True except Exception: print(f失效代理{proxy}) return False def init_proxy_pool(self): 初始化并清洗代理池 print(正在刷新代理池筛选可用IP...) raw_proxies self.get_free_proxies() if not raw_proxies: print(本次未获取到任何代理IP) return # 只保留有效IP valid_proxies [p for p in raw_proxies if self.check_proxy(p)] self.proxy_list valid_proxies print(f代理池刷新完成当前可用IP数量{len(self.proxy_list)}) def get_random_proxy(self): 随机拿一个可用代理空了就自动刷新 if not self.proxy_list: print(代理池空了自动重新更新中...) self.init_proxy_pool() return random.choice(self.proxy_list) if self.proxy_list else None def remove_invalid_proxy(self, proxy): 删掉失效的代理 if proxy in self.proxy_list: self.proxy_list.remove(proxy) print(f移除失效IP{proxy}剩余可用{len(self.proxy_list)}) def proxy_request(self, url, methodGET, **kwargs): 自带IP轮换、重试的请求方法直接替代原生requests.get/post retry_count 0 while retry_count self.max_retry: proxy self.get_random_proxy() if not proxy: raise Exception(当前无可用代理) proxies { http: fhttp://{proxy}, https: fhttp://{proxy} } try: kwargs[proxies] proxies kwargs[timeout] self.timeout if method.upper() GET: res requests.get(url, **kwargs) elif method.upper() POST: res requests.post(url, **kwargs) else: raise Exception(仅支持 GET / POST) print(f请求成功本次IP{proxy}) return res except Exception: retry_count 1 self.remove_invalid_proxy(proxy) print(f请求失败换IP重试剩余次数{self.max_retry - retry_count}) time.sleep(1) raise Exception(多次重试全部失败暂无可用代理) # 全局实例化全程复用 proxy_pool ProxyPool() proxy_pool.init_proxy_pool()简单测试一下看IP是不是真的在轮换写个几行测试代码跑五次请求就能明显看到每次IP都不一样if __name__ __main__: test_url http://httpbin.org/ip for i in range(5): try: resp proxy_pool.proxy_request(test_url) print(f第{i1}次请求IP{resp.text}\n) except Exception as e: print(f第{i1}次请求失败{e}\n) time.sleep(1)跑通之后你会发现失效IP自动剔除、空池自动更新、每次请求随机换IP整个过程完全不用自己管极其省心。长期使用我加的几个实用优化非常有用1. 后台定时自动刷新代理池代理IP都是短命的长期跑爬虫必须定时更新我一般10分钟刷一次import threading def refresh_proxy_pool(): while True: time.sleep(600) proxy_pool.init_proxy_pool() # 后台线程默默运行不影响主程序 threading.Thread(targetrefresh_proxy_pool, daemonTrue).start()2. 免费代理仅学习用生产务必换付费这点我真心建议大家免费代理玩玩就行存活率极低、经常超时。真正做项目直接对接付费代理API替换掉代码里的代理接口即可稳定性直接翻倍。3. 别高频狂请求就算有代理池也别一秒几十次乱请求。适当加随机休眠模拟真人浏览节奏风控概率会更低。平时最常见的问题汇总Q为什么我成功率很低、老是超时基本都是免费代理本身质量差换付费代理、稍微调大超时时间就能解决。Q为什么有时候代理池直接空了免费接口IP数量有限、失效快开启定时刷新或者直接换付费接口就稳了。QHTTPS 网站请求失败怎么回事部分老旧免费代理不支持HTTPS尽量筛选高匿通用代理即可。最后小结说实话对于绝大多数个人爬虫、中小型项目根本不用上 Redis 分布式代理池。我这套轻量轮换方案零额外组件、代码少、好维护、全自动完全够用。只要你不是超大规模分布式爬虫这套代码直接拿去长期跑项目完全没问题彻底告别爬虫被封IP的烦恼。