在尝试从一个使用Cloudflare Web应用程序防火墙(WAF)保护的网站获取数据时,我遇到了一些挑战.该网站的安全措施非常严格,以至于在正常浏览几个页面后,Cloudflare的检查页面就会出现.

传统的HTTP客户端方法,如直接使用httpclient来抓取页面数据,很快就会遭遇阻碍.

即便尝试使用代理IP池,问题依旧存在,因为Cloudflare的检测机制能够在短时间内多次访问后迅速触发.在多次尝试后,我决定使用playwright这个自动化库来模拟正常的浏览器行为.

虽然在使用playwright的过程中遇到了一些问题,但我最终找到了解决方案.现在,尽管速度稍慢,但我能够正常地从网站获取数据.接下来,我将分享如何克服这些挑战的经验.

直接403

这是cloudflare的基本防护,他会检查是否使用了webdriver进行模拟爬取.

解决方式:

...
final BrowserContext context = browser.newContext();
...
context.setDefaultTimeout(180_000);
context.setDefaultNavigationTimeout(180_000);
context.addInitScript("Object.defineProperty(navigator, 'webdriver', {get: () => undefined})");

这里同时也将默认超时拉长,避免在等待某些元素触发的条件下超时.

使用本地安装的浏览器

可以直接指定本地安装的浏览器:

While Playwright can download and use the recent Chromium build, it can operate against the branded Google Chrome and Microsoft Edge browsers available on the machine (note that Playwright doesn't install them by default). In particular, the current Playwright version will support Stable and Beta channels of these browsers.

Available channels are chrome, msedge, chrome-beta, msedge-beta or msedge-dev.

启动的时候指定即可:

Browser browser = playwright.chromium().launch(new BrowserType.LaunchOptions().setChannel("msedge"));

是否触发了cloudflare判断

因为触发了cloudflare页面的url并不会有明显的变化,只有多一次跳转.

这里直接使用页面元素即可, 处理代码如下:

    private static void checkMeetChallenge(Page page) throws Exception {
ElementHandle stage = page.querySelector("div#challenge-stage");
int checkCount = 1;
while (stage != null) {
tryToClickChallenge(page, stage);
if (checkCount >= 6) {
if (page.querySelector("div#challenge-stage") != null) {
throw new Exception("meet challenge restart");
}
}
log.info("handleCategory - meet challenge. wait 20s to check it again. count:{}", checkCount);
checkCount++;
page.waitForTimeout(20_000);
stage = page.querySelector("div#challenge-stage");
}
}

在上层的调用代码中,我先判断了我需要的元素是否存在,如果不存在有两种可能,一种是已经爬完了,另一种是触发了cloudflare.

那个meet challenge restart是一层兜底, 如果点击失败加上长时间等待还在, 那就重启浏览器, 重启之后大概率不会重新触发防护, 也算是最后一个措施了.

处理防护页的人工点击

首先先看一下那个防护页面的结构:

<div id="challenge-stage" style="display: flex;">
<div id="turnstile-wrapper" class="captcha-prompt spacer">
<div><iframe
src="https://challenges.cloudflare.com/cdn-cgi/challenge-platform/xxxxxx"
allow="cross-origin-isolated; fullscreen"
sandbox="allow-same-origin allow-scripts allow-popups" id="cf-chl-widget-sppzq" tabindex="0"
title="包含 Cloudflare 安全质询的小组件 "
style="border: none; overflow: hidden; width: 300px; height: 65px;"></iframe><input
type="hidden" name="cf-turnstile-response" id="cf-chl-widget-sppzq_response"></div>
</div>
</div>

点击的组件被放在了一个iframe里,正常要获取元素点击比较麻烦.

但是playwright直接模拟鼠标在位置上点击即可.

具体思路是定位到外层的div#challenge-stage, 然后用page.mouse().move移动到元素上,在用click()点击.

代码:

BoundingBox box = stageDiv.boundingBox();
page.mouse().move(box.x + 100, box.y + box.height / 2);
page.waitForTimeout(1_000 + ThreadLocalRandom.current().nextInt(100, 1000));
page.mouse().click(box.x + 100, box.y + box.height / 2);

其实你不点击它也没关系,我在测试的时候发现这个challenge页面会在1分钟左右自己消失,可以在检测出是challenge之后循环waitForTimeout即可.

最后就是要注意时间间隔,中间留一点时间.

这些做完基本就可以慢慢获取数据了.

我之前还做了很多随机滚动(mouse.wheel),移动到下一页点击等措施,结果发现做不做一样,可能在一些情况下比较有用.

因为playwright很多动作其实是要scheduled的,它并不立即触发,比如你click下一页之后就算waitForLoadState再用locatorquerySelector获取元素他还是会报错,这种情况可以手动waitForTimeout一下,我不知道这样处理是不是常规做法,但至少解决了我的问题.

相关参考链接:

playwright

playwright Browsers

How to Bypass Cloudflare with Playwright in 2024

original blog

playwright 一些方法解决cloudflare防护页的问题的更多相关文章

  1. 解决vue单页路由跳转后scrollTop的问题

    作为vue的初级使用者,在开发过程中遇到的坑太多了.在看页面的时候发现了页面滚动的问题,当一个页面滚动了,点击页面上的路由调到下一个页面时,跳转后的页面也是滚动的,滚动条并不是在页面的顶部 在我们写路 ...

  2. CloudFlare防护下的破绽:寻找真实IP的几条途径

    本文仅代表作者独立观点,本文提及的技术仅供安全研究和渗透测试用途 看Twitter发现CloudFlare总裁什么的最近很高调,北京.香港的跑着参加会议.发表演说什么的,CloudFlare似乎也没那 ...

  3. 学习笔记:Maven构造版本号的方法解决浏览器缓存问题

    需要解决的问题 在做WEB系统开发时,为了提高性能会利用浏览器的缓存功能,其实即使不显式的申明缓存,现代的浏览器都会对静态文件(js.css.图片之类)缓存.但也正因为这个问题导致一个问题,就是资源的 ...

  4. (转)再不用担心DataRow类型转换和空值了(使用扩展方法解决高频问题)

    再不用担心DataRow类型转换和空值了(使用扩展方法解决高频问题) XML文档操作集锦(C#篇) webapi文档描述-swagger

  5. BeginInvoke与EndInvoke方法解决多线程接收委托返回值问题

    BeginInvoke与EndInvoke方法解决多线程接收委托返回值问题 原文:http://www.sufeinet.com/thread-3707-1-1.html      大家可以先看看我上 ...

  6. ASP.Net MVC_DotNetZip简单使用方法,解决文件压缩的问题[转]

    准备工作: 在vs工具栏中找到NuGet   下载DotNetZip   现在就可以使用DotNetZip强大的类库了,在这里我给出一些简单的使用. ? 1 2 3 4 5 6 7 8 9 10 11 ...

  7. jquery prop()方法 解决全选 不全选 反选 问题 解决执行一次不不能再执行问题

    //1.如果通过prop()函数更改<input>和<button>元素的type属性,在多数浏览器上将会抛出一个错误,因为该属性一般不允许在后期更改.//如果使用prop() ...

  8. YouTube为什么打不开?以及简便的訪问的方法/解决方式!

    在站点统计中看到好多人通过百度或者谷歌(Google)搜索引擎搜:YouTube怎么上不去,怎样不用代理server訪问YouTube,YouTube上不去的解决的方法,YouTube怎样訪问等等.事 ...

  9. 使用.netFx4.0提供的方法解决32位程序访问64位系统的64位注册表

    原文:使用.netFx4.0提供的方法解决32位程序访问64位系统的64位注册表 我们知道目标平台是32位的程序运行在64位的系统上,去访问部分注册表的时候系统自动重定向到win32node节点对应的 ...

  10. windows server 2008见安装IIS方法(解决)

    windows server 2008见安装IIS方法(解决) 刚开始有点蒙,后来才知道原来如此.! . 右键点击[我的电脑]--[管理]--[字符]--[加入角色]--仅落后win7像.啊! 版权声 ...

随机推荐

  1. SpringBoot 学习笔记:运维篇

    SpringBoot程序的打包和运行 开发部门使用Git.SVN等版本控制工具上传工程到版本服务器 服务器使用版本控制工具下载工程 服务器上使用Maven工具在当前真机环境下重新构建项目 启动服务 程 ...

  2. S3C2440移植uboot之编译烧写uboot

    目录 移植环境 获取uboot 更新交叉编译工具 配置环境变量 移植环境 主 机:VMWare--ubuntu16.04 开发板:S3C2440 编译器:arm-linux-gcc-4.3.2.tgz ...

  3. P3842-DP【黄】

    想搜索到最后一层,就必得先完成前面层的搜索任务,这构成了对状态转移的启示,即当前层的DP值应该是此前层转移过来后得到的最佳值. 但这道题看数据范围应该不能用二维数组,抱着侥幸的心理我使用了动态二维数组 ...

  4. Blazor模式讲解

    Blazor的三种模式 Blazor Server: Blazor Server在 ASP.NET Core 应用中支持在服务器上托管 Razor 组件. 可通过 SignalR 连接处理 UI 更新 ...

  5. SpringCloud对使用者透明的数据同步组件

    一.背景 云端使用Spring Cloud实现,A服务有一些数据,B和C服务也需要A服务的这些数据,但是系统上面只有A服务有数据操作的入口,B和C服务只能从A服务处同步数据到自己的表里面. 解决方案是 ...

  6. JMS微服务开发示例(七)使用 Serilog 作为日志提供者

    nuget 引入: Serilog.Extensions.LoggingSerilog.Settings.ConfigurationSerilog.Sinks.ConsoleSerilog.Sinks ...

  7. [转帖]Oracle nvarchar2存储特殊字符乱码问题

    https://www.cnblogs.com/PiscesCanon/p/15157506.html 这个问题研究了一天多,终于搞定了. 起因是业务需要存特殊字符'ø'到varchar2的字段中出现 ...

  8. MySQL shell 备份数据库

    MySQL shell 备份数据库 背景 之前使用 mysqldump 和 mysql source 的方式备份数据库非常缓慢 有时候要耗费非常长的时间 今天发现有一个可以快速备份数据库的 mysql ...

  9. [转帖]一文读懂 | 如何快速部署 OceanBase 开源版

    2021-11-281398 版权 本文涉及的产品 云数据库 RDS MySQL Serverless,0.5-2RCU 50GB 推荐场景: 学生管理系统数据库设计搭建个人博客 立即试用 云防火墙, ...

  10. [转帖]使用Rclone实现minio数据的迁移

    使用Rclone实现minio数据的迁移 一.准备 1.1 使用工具 rclone:开源的对象存储在线迁移工具,用于文件和目录的同步,支持阿里云的oss.minio .亚马逊S3 等. 1.2 注意事 ...