
本地跑得好好的爬虫一放到服务器上跑量就开始各种报错——403、412、429严重一点直接甩给你一个验证码页面。代码逻辑我检查了三遍没毛病。说实话做数据采集这几年被封IP坑过的次数我自己都数不清了。后来才慢慢想明白封禁的锅很多时候真不在你的代码而在于——你在服务器眼里不像个正常用户。这篇文章我想把这件事一次讲透。分三块平台到底靠什么判断你是爬虫从轻到重6 种应对方案含代码重点落地怎么给爬虫接一个代理IP池一、平台怎么认出你是爬虫的很多人以为反爬是检测你是不是脚本其实没那么玄乎。平台手里有一堆维度任何一个异常都可能让你进黑名单。常见的有这几类请求频率与行为特征这是最基础的。正常用户点一下停几秒你的爬虫一秒发几十次请求这特征太扎眼了。除了频率还有行为模式——比如你总是按固定顺序翻页、请求间隔精确到毫秒、深夜三点还在稳定高频请求这些都不像人。请求指纹你的浏览器和脚本发出去的请求长得不一样。平台看这些User-Agent 是 Python-requests 还是真实 Chrome请求头字段的顺序、大小写、有没有缺失字段TLS 握手的指纹JA3 之类python 的 TLS 库跟 Chrome 天然不同Accept、Accept-Language、Referer 是否合理一个 User-Agent 是 Chrome但其它头跟 Chrome 完全对不上的请求一眼假。3. IP 维度这是很多人忽略的一环。平台会看单 IP 的请求量同一个 IP 短时间内请求过多IP 信誉 / 纯净度这个 IP 之前有没有被封过、是不是数据中心 IPIP 的地理与运营商你昨天在广州今天 IP 跳到哈尔滨明天又在成都行为很怪机房 IPIDC 数据中心 IP经常被平台提前标记因为真实用户很少从机房上网。4. 登录态与签名像 B站、抖音、小红书这类平台接口都带了签名参数比如各种 w_rid、a_bogus、X-s 之类还会校验登录 Cookie。你签名算法不对、Cookie 无效请求直接就被拒了。这块属于硬对抗本文不展开重点是前面三个——因为它们才是大多数人被封的主因。二、6 种解决方案从轻到重按投入成本排序你可以按自己的量级选。方案 1请求头伪装成本最低先做这个别再用裸的 requests.get(url) 了。先把请求头补齐python复制import requestsheaders {“User-Agent”: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 “(KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36”,“Referer”: “https://目标网站.com/”,“Accept”: “text/html,application/xhtmlxml,application/xml;q0.9,/;q0.8”,“Accept-Language”: “zh-CN,zh;q0.9”,}resp requests.get(“https://目标网站.com/list”, headersheaders, timeout10)print(resp.status_code)能解决最简单的一眼假检测。解决不了频率限制、IP 封禁、签名校验。小提醒User-Agent 别老用同一个。可以准备一个列表随机挑配合主流浏览器版本。方案 2随机延时 退避重试性价比很高就算你用了代理也不建议毫无间隔地狂发请求。加一点随机性效果提升明显python复制import timeimport randomimport requestsdef fetch(url, retries3):for i in range(retries):try:resp requests.get(url, timeout10)if resp.status_code 200:return resp.text# 被限流了按指数退避再试time.sleep((2 ** i) random.uniform(0, 1))except requests.RequestException:time.sleep(1)return Nonefor page in range(1, 51):html fetch(fhttps://目标网站.com/list?page{page}“)# 每页之间随机停一下别让它看起来像机器time.sleep(random.uniform(1, 3))关键点延时一定要随机”固定 sleep(1) 反而是一种特征。方案 3Cookie / 登录态池有些数据必须登录才能拿到。这时候单个账号不够需要准备多个账号的 Cookie轮换使用。思路很简单把多个账号的 Cookie 存成一个列表每次请求随机取一个。注意每个账号的请求频率也要控制否则账号会被封。python复制import randomimport requestscookie_pool [“sessionidxxx1; other…”,“sessionidxxx2; other…”,]def get_headers():return {“User-Agent”: “Mozilla/5.0 … Chrome/124.0.0.0 Safari/537.36”,“Cookie”: random.choice(cookie_pool),}方案 4浏览器自动化对抗强一些的网站当网站大量依赖 JS 渲染、或者有复杂指纹检测时requests 就不够用了。这时候上 Playwright / Selenium直接驱动一个真实浏览器python复制from playwright.sync_api import sync_playwrightwith sync_playwright() as p:browser p.chromium.launch(headlessTrue)page browser.new_page()page.goto(“https://目标网站.com”)content page.content()browser.close()代价速度慢、资源消耗大、不适合大规模采集。适用数据量不大、但对真实性要求高的场景。方案 5代理IP池规模采集的核心如果你的采集量上来了前几种方法都只是缓解真正决定能不能稳定跑下去的是代理IP。原理不复杂请求不再直接从你的服务器发出去而是先经过代理服务器转发目标网站看到的是代理的 IP不是你自己的。这样你就能把请求压力分散到大量不同的 IP 上让每个 IP 看起来都没那么高频。python复制proxies {“http”: “http://用户名:密码代理地址:端口”,“https”: “http://用户名:密码代理地址:端口”,}resp requests.get(“https://目标网站.com/list”, proxiesproxies, timeout10)方案 6遵守 robots 控制规模合规底线前面说的都是技术对抗但有一条底线得先讲清楚爬虫要合法合规。先看 robots.txt别碰明确禁止的路径涉及个人隐私、付费内容、需要授权才能拿的数据别碰控制规模别把人家网站压垮用途合法别拿数据去做违法的事技术只是工具用在什么地方是你自己的选择。三、重点实战给爬虫接一个代理IP池上面方案 5 只是最基础的用法——单个代理。真实场景里你需要的是一个会自己换 IP 的池子。我把自己常用的一个轻量实现贴出来。第一步从服务商 API 批量提取 IP正规的代理服务商都会提供 API 提取接口直接拉一批 IP 回来python复制import randomimport requestsclass ProxyPool:definit(self, api_url):self.api_url api_urlself.pool []self.refresh()def refresh(self): 从代理服务商 API 批量提取 IP resp requests.get(self.api_url, timeout10) self.pool [line.strip() for line in resp.text.splitlines() if line.strip()] print(f已补充 IP{len(self.pool)} 个) def get(self): 随机取一个 IP池子空了就补 if not self.pool: self.refresh() return random.choice(self.pool) def check(self, proxy): 检测这个 IP 还能不能用 try: r requests.get( http://httpbin.org/ip, proxies{http: fhttp://{proxy}, https: fhttp://{proxy}}, timeout5, ) return r.status_code 200 except Exception: return False第二步带着池子跑采集python复制pool ProxyPool(“https://你的代理服务商/api/get?count10”)headers {“User-Agent”: “Mozilla/5.0 … Chrome/124.0.0.0 Safari/537.36”,}for page in range(1, 101):proxy pool.get()proxies {“http”: fhttp://{proxy}“, “https”: fhttp://{proxy}”}try: r requests.get( fhttps://目标网站.com/list?page{page}, headersheaders, proxiesproxies, timeout10, ) parse(r.text) # 你的解析逻辑 except Exception: # 这个 IP 挂了剔掉下次自动换 pass # 每请求一次随机停一下 time.sleep(random.uniform(1, 3))第三步几个容易踩的坑坑 1不检测直接用。代理池里总有失效的 IP。开跑前、用之前最好过一遍 check()。不然你的解析逻辑会莫名其妙拿不到数据。坑 2返回空页面却没报错。有些网站被限流时不返回错误码而是返回一个看起来正常但内容是空的页面或者验证码页。所以解析完一定要校验关键字段——比如一页 20 条数据如果 15 条标题是空的那就说明出问题了。坑 3只看 IP 数量不看 IP 质量。机房 IP 便宜但被标记得厉害很多平台直接拒。住宅 IP家庭宽带 IP纯净度高、更像真实用户适合对隐蔽性要求高的采集。四、代理IP 怎么选才不踩坑市面上的代理 IP 服务商很多参数看得人眼花。我按自己踩坑的经验给你几个真正影响结果的指标指标怎么理解建议IP 类型住宅IP / 机房IP要稳定隐蔽选住宅纯速度场景可用机房纯净度该 IP 被风控标记的程度越低越好直接决定可用性可用率提取出来的 IP 能用的比例越高越省心别只看 IP 池大小IP 时效长效不变/ 短效常换需会话保持选长效高频轮换选短效并发同时能发多少请求按你的量级配别一步到位覆盖地区能指定的省市要按地区采集就得看这个一句话别只比价格和 IP 数量纯净度和可用率才是决定你效率的东西。五、避坑清单照着自查请求头补齐了吗别裸奔延时是随机的吗固定 sleep 也是特征代理用之前检测过可用性吗解析后校验了关键字段吗防空页面陷阱IP 类型选对了吗住宅 vs 机房频率压得住吗再好的 IP 也扛不住无脑高频用途合法吗robots 看了吗六、常见问题FAQQ1用了代理为什么还是被封大概率是代理 IP 本身不干净机房 IP 被标记或者你的请求行为特征太明显频率、头信息。IP 只是其中一环。Q2免费代理能用吗偶尔测试可以正式项目别用。免费代理普遍存活时间短、速度慢、数量少反而拖慢你的效率还可能被拿去做中间人攻击。Q3多长时间换一次 IP 合适看网站风控强度和你的量。一般小规模采集 1~3 分钟换一次量大的话可以一次一换。核心是让单个 IP 的请求频率看起来正常。Q4住宅IP 和机房IP 到底差在哪住宅IP 来自真实家庭宽带行为跟普通用户一致难被识别适合隐蔽性要求高的场景机房IP 来自数据中心速度快、便宜但容易被平台标记。写在最后爬虫被封说到底是一场像不像真人的博弈。请求头、延时、Cookie、指纹、代理IP都是围绕这一件事做文章。量级小的时候前两三种方案就够用真要长期、稳定、大规模地跑代理IP池是绕不开的基础设施。我这边用的是国内住宅静态代理覆盖 30 多个省份、300 多个城市纯净度不错跑数据采集和电商类的项目比较省心。感兴趣可以去官网看看90daili.com合法合规用途仅提供国内节点。技术这东西多踩几次坑就熟了。有问题的欢迎评论区聊看到都会回。本文为原创技术分享涉及的采集思想仅供学习与合法用途参考。请遵守目标网站的 robots 协议及相关法律法规。