当前位置: 首页 > news >正文

爬虫反爬进阶——IP代理池、请求指纹、字体反爬实战

入门级反爬(User-Agent、IP 封禁、请求频率限制)好解决,但到了进阶阶段,会遇到更多花样。这篇讲三个最实用的反爬对抗技术。

一、IP 代理池——突破封 IP

爬得稍微快一点,网站就封 IP。解决方案是维护一个代理池,IP 被封了自动换。

1. 免费代理获取(思路)

importrequestsfrombs4importBeautifulSoupimporttimedeffetch_free_proxies():"""从免费代理网站采集代理IP(示例)"""proxies=[]url="https://www.free-proxy-list.com/"resp=requests.get(url,headers={"User-Agent":"Mozilla/5.0"})soup=BeautifulSoup(resp.text,"html.parser")forrowinsoup.select("table tr")[1:]:# 跳过表头cols=row.select("td")iflen(cols)>=2:ip=cols[0].text.strip()port=cols[1].text.strip()proxies.append(f"{ip}:{port}")returnproxies

需要注意的是:免费代理质量很差(90% 不可用,速度慢),小规模采集凑合用,大规模采集建议买付费代理。

2. 验证代理是否可用

importthreadingdefcheck_proxy(proxy):"""测试代理是否可用"""try:resp=requests.get("http://httpbin.org/ip",proxies={"http":proxy,"https":proxy},timeout=5)ifresp.status_code==200:print(f"✅{proxy}可用 -{resp.text.strip()}")returnTrueexcept:passreturnFalse# 多线程验证所有代理defvalidate_all(proxies):valid=[]threads=[]lock=threading.Lock()defcheck(p):ifcheck_proxy(p):withlock:valid.append(p)forpinproxies:t=threading.Thread(target=check,args=(p,))t.start()threads.append(t)fortinthreads:t.join()returnvalid

3. 代理池管理器

importrandomimporttimeimportrequestsclassProxyPool:"""简单的代理池管理器"""def__init__(self):self.proxies=[]self.blacklist=set()defadd_proxy(self,proxy):ifproxynotinself.blacklist:self.proxies.append(proxy)defget_proxy(self):"""随机返回一个代理"""ifnotself.proxies:returnNonereturnrandom.choice(self.proxies)defmark_bad(self,proxy):"""标记代理不可用"""ifproxyinself.proxies:self.proxies.remove(proxy)self.blacklist.add(proxy)print(f"💀 代理{proxy}已移除,剩余{len(self.proxies)}个")defrequest_with_retry(self,url,max_retries=5):"""带代理重试的请求"""foriinrange(max_retries):proxy=self.get_proxy()ifnotproxy:print("代理池已空,等待补充...")returnNonetry:resp=requests.get(url,proxies={"http":proxy,"https":proxy},timeout=10,headers={"User-Agent":"Mozilla/5.0"})ifresp.status_code==200:returnrespelse:self.mark_bad(proxy)except:self.mark_bad(proxy)time.sleep(0.5)print(f"重试{max_retries}次全部失败:{url}")returnNone

4. 付费代理推荐

免费代理不稳定,真干活建议买:

  • 快代理:国内最大的代理服务商,动态代理按量计费
  • 芝麻代理:价格便宜,几块钱能用一天
  • 站大爷:支持动态按需提取

一般几十块钱能用几个月,省心很多。

二、请求指纹——伪装浏览器特征

现在的反爬不仅看 IP 和 UA,还会检测TLS 指纹、Headers 顺序、WebDriver等。

1. 完整的请求头伪装

headers={"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/125.0.0.0 Safari/537.36","Accept":"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8","Accept-Language":"zh-CN,zh;q=0.9,en;q=0.8","Accept-Encoding":"gzip, deflate, br","Connection":"keep-alive","Referer":"https://www.google.com/","Sec-Ch-Ua":'"Google Chrome";v="125", "Chromium";v="125", "Not.A/Brand";v="24"',"Sec-Ch-Ua-Mobile":"?0","Sec-Ch-Ua-Platform":'"Windows"',"Sec-Fetch-Dest":"document","Sec-Fetch-Mode":"navigate","Sec-Fetch-Site":"none","Sec-Fetch-User":"?1","Upgrade-Insecure-Requests":"1",}

2. 随机切换

importrandomfromfake_useragentimportUserAgent ua=UserAgent()classRandomHeaders:"""随机生成请求头"""@staticmethoddefget_headers():user_agents=[ua.chrome,ua.edge,ua.firefox,]return{"User-Agent":random.choice(user_agents),"Accept":"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8","Accept-Language":random.choice(["zh-CN,zh;q=0.9,en;q=0.8","en-US,en;q=0.9,zh-CN;q=0.8","zh-CN,zh;q=0.9",]),"Referer":random.choice(["https://www.baidu.com/","https://www.google.com/","https://www.bing.com/",]),}

3. 使用 requests 会话重用

# 每次都新建会话,容易被识别# 正确的做法是复用 Sessionsession=requests.Session()session.headers.update(RandomHeaders.get_headers())# 连续请求,保持同一指纹resp1=session.get("https://example.com/page1")resp2=session.get("https://example.com/page2")

三、字体反爬——最常见的反爬手段

很多网站(大众点评、猫眼电影、58同城)用自定义字体来加密数字,你爬下来看到的是乱码。

原理

正常数字:0 1 2 3 4 5 6 7 8 9 加密后: ➀ ➁ ➂ ➃ ➄ ➅ ➆ ➇ ➈ ➉ 网页通过 @font-face 加载一个自定义字体文件(.woff 或 .ttf) 字体文件里把字符映射关系打乱了 所以浏览器能正确显示,但你爬到的文本是乱码

解决方案

fromfontTools.ttLibimportTTFontimportreimportrequestsdefparse_font_anti_spider(html_text,font_url):"""解析字体反爬"""# 1. 下载字体文件resp=requests.get(font_url)withopen("temp.woff","wb")asf:f.write(resp.content)# 2. 解析字体映射关系font=TTFont("temp.woff")cmap=font.getBestCmap()# 3. 建立映射关系# cmap 返回的是 {unicode编码: 字形名称}# 比如 {0xe001: 'one', 0xe002: 'two', ...}# 需要根据字形名称找到对应的数字unicode_to_digit={}num_map={"one":"1","two":"2","three":"3","four":"4","five":"5","six":"6","seven":"7","eight":"8","nine":"9","zero":"0",}forunicode_val,glyph_nameincmap.items():# 字形名称可能类似 "uniE001" 或 "one"glyph_name=glyph_name.lower()foreng,digitinnum_map.items():ifenginglyph_name:unicode_to_digit[chr(unicode_val)]=digit# 4. 替换加密字符forenc_char,digitinunicode_to_digit.items():html_text=html_text.replace(enc_char,digit)returnhtml_text

在线字体反爬(动态加载更麻烦)

很多网站已经升级到了动态字体——每次请求都生成新的字体文件,映射关系每次都不一样:

# 解决方案思路:# 1. 每次请求都下载最新的字体文件# 2. 通过字形轮廓计算来识别数字# 更简单的方法:用 OCR 识别# from PIL import Image# import pytesseract# 但准确率不如直接解析字体文件

四、Selenium 防检测

用 Selenium 时,网站可以通过window.navigator.webdriver检测到你是自动化工具。

1. 隐藏 WebDriver 特征

fromseleniumimportwebdriverfromselenium.webdriver.chrome.optionsimportOptions options=Options()options.add_argument("--disable-blink-features=AutomationControlled")options.add_experimental_option("excludeSwitches",["enable-automation"])options.add_experimental_option("useAutomationExtension",False)driver=webdriver.Chrome(options=options)# 注入 JS 修改 navigator 属性driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument",{"source":""" Object.defineProperty(navigator, 'webdriver', { get: () => undefined }); Object.defineProperty(navigator, 'plugins', { get: () => [1, 2, 3, 4, 5] }); Object.defineProperty(navigator, 'languages', { get: () => ['zh-CN', 'zh'] }); """})

2. 使用 undetected-chromedriver

有个专门的库解决了大部分检测问题:

pipinstallundetected-chromedriver
importundetected_chromedriverasuc driver=uc.Chrome()driver.get("https://example.com")# 自动隐藏了 WebDriver 特征,比手动配置稳定得多

五、实际工作流:如何选择反爬策略

反爬级别特征应对方法
⭐ 入门级封 IP、限频率加延时 + 轮换 UA
⭐⭐ 初级检测请求头、验证码Session 复用 + 代理池
⭐⭐⭐ 中级字体反爬、动态加载下载字体解析 + 抓接口
⭐⭐⭐⭐ 高级WebDriver 检测、风控系统undetected-chromedriver + 行为模拟
⭐⭐⭐⭐⭐ 顶级滑块验证、人机识别打码平台 + 行为轨迹模拟

核心原则:反爬对抗不是越强越好,够用就行。加 3 秒延迟 + 轮换 UA 能解决 80% 的问题,没必要一上来就上分布式代理池。


💡 觉得有用的话,点赞 + 关注【张老师技术栈】吧!每周更新 Java/Python/爬虫 实战干货,不让你白来。

http://www.gsyq.cn/news/1595627.html

相关文章:

  • VRPN:异构设备网络化集成的核心协议与实战指南
  • ArkUI 状态管理与页面交互核心:@State、弹窗与路由
  • 【供应链建设】伸缩延长杆源头工厂供应商的工程能力是建立供应链的关键
  • 如何快速掌握鼠标连点器:面向新手的完整自动化工具指南
  • Qwerty Learner:如何通过打字练习重构你的英语肌肉记忆?
  • 鸿翼OpenContent™ AI智能多模态数据管理平台介绍与功能场景
  • GitHub今日热榜 | 2026-06-25:Agent开发环境爆发,7个项目首次入榜
  • TranslucentTB:Windows任务栏透明化终极指南,打造个性化桌面体验
  • Spring Boot 集成 Tess4J 实现图片OCR文字识别
  • 5分钟快速上手《经济研究》LaTeX投稿模板:终极排版解决方案
  • 全栈开发别再瞎加班了!10 个 AI 神器 + 3 个实战项目,效率直接翻 3 倍
  • 终极AI小说推文自动化:6小时从文字到视频的完整解决方案
  • 目前靠谱的AI智能体网站哪家可靠
  • 微软CEO:别只顾接入AI,你的知识正在被大模型吸走
  • 2026年,探秘专业高压塑料膜生产商的制胜秘诀
  • Java IDE迁移决策白皮书(IntelliJ IDEA与MyEclipse深度横评):基于37个真实团队、892小时IDE使用日志与217份开发者问卷的权威结论
  • 工业级差分晶振选型与应用全解析
  • 一支能打硬仗的队伍,长沙迪迈科技的组织凝聚力从何而来
  • Codex可以批量生成图片提示词吗?Claude润色后做电商主图流程
  • Hermes Agent实战指南:基于LangGraph的可控智能体工作流搭建
  • 终极实战指南:如何用dnSpyEx进行专业级.NET程序集分析与逆向工程
  • 三菱 FX 系列 PLC学习程序分享- 5 层电梯完整 PLC 项目程序
  • ESP32同步整流MPPT降压系统设计与效率优化
  • Balena Etcher 终极指南:如何在Linux系统上轻松创建可启动设备?
  • Selenium自动化测试实战:从环境搭建到框架设计与CI/CD集成
  • DBX:15MB 的小钢炮,如何塞下 50+ 种数据库
  • Nintendo Switch大气层系统:革命性安全架构与模块化自定义固件解决方案
  • 玉石五轴机选型避坑:3个隐性指标比纸面精度更重要
  • 2d 横版 动作游戏 免费开源!
  • React 并发渲染:Suspense 与 Transition 的底层调度机制