使用pyppeteer进行网页抓取时遭遇站点拦截,尝试多种方案均无效该如何解决?
可行修复方案
优先添加浏览器指纹隐藏插件
原生Puppeteer存在大量可被反爬系统识别的特征(如navigator.webdriver返回true、缺失正常浏览器的plugins/fonts参数、webdriver标记残留等),你需要接入对应版本的stealth插件来抹除这些特征,pyppeteer环境可以直接安装pyppeteer-stealth实现。修正请求头冲突问题
你当前全局页面设置的UA为Chrome 91版本,但拦截特定请求时又替换为Chrome 71版本,两个UA版本不一致属于明显的异常请求特征,统一所有请求的UA版本,且尽量和你启动的Chrome实际版本保持一致,同时删除你自定义的Connection: close参数,正常浏览器默认会携带Connection: keep-alive,人为修改反而会被反爬标记。更换住宅IP类型代理
普通数据中心IP代理几乎已经被所有主流电商、优惠券站点拉黑,你需要更换为住宅家庭带宽类型的代理,同时确保代理IP的所在地、时区和你请求头中Accept-Language的地区对应,避免出现IP属地为国内、但语言设置为全英文的异常情况。修复页面跳转等待逻辑
你当前同时触发page.goto和page.waitForNavigation的写法存在逻辑错误,容易出现超时、跳转捕获失败的问题,直接在page.goto中指定等待条件即可,不需要额外加waitForNavigation。先关闭请求拦截验证
请求拦截功能会修改浏览器默认的请求头顺序、资源加载时序,部分反爬系统会检测这类异常,你可以先关闭请求拦截逻辑,测试是否可以正常访问,确认是不是修改请求的操作触发了拦截。
修改后的参考代码
# 首先安装依赖:pip install pyppeteer-extra pyppeteer-stealth from pyppeteer_stealth import stealth args = [ '--start-maximized', '--disable-extensions', '--hide-scrollbars', '--disable-bundled-ppapi-flash', '--mute-audio', '--no-sandbox', '--disable-setuid-sandbox', '--disable-gpu', '--proxy-server='+self.PROXY_HOST+':'+str(self.PROXY_PORT), # 新增参数禁用webdriver标记 '--disable-blink-features=AutomationControlled' ] browser = await launch(headless=False, options={'args': args}) browser_context = await browser.createIncognitoBrowserContext() page = await browser_context.newPage() # 应用stealth隐藏所有浏览器指纹特征 await stealth(page) # 统一UA,注意和你实际启动的Chrome版本匹配 COMMON_UA = 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36' await page.setUserAgent(COMMON_UA) await page.setExtraHTTPHeaders({ "Accept" : "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "Accept-Language" : "zh-CN,zh;q=0.9,en;q=0.8", "Accept-Encoding" : "gzip, deflate, br" }) await page.setViewport({ 'width': 1366, 'height': 768 }) await page.authenticate({'username': self.PROXY_USER, 'password': self.PROXY_PASS}) # 先注释掉请求拦截逻辑,测试正常访问后再按需开启 # await page.setRequestInterception(True) # async def intercept(request): # if "origem=PD" in request.url: # await request.continue_({ # "headers": { # **request.headers, # 'User-Agent': COMMON_UA, # } # }) # else: # await request.continue_() # page.on('request', lambda req: asyncio.ensure_future(intercept(req))) # 修正跳转等待逻辑 await page.goto(url, {'waitUntil': 'networkidle2', 'timeout': 60000}) # 按需添加延时等待页面静态资源、动态脚本加载完成 await page.waitForTimeout(3000) content = await page.content()
内容的提问来源于stack exchange,提问作者israel

