返回博客
指南
米赫内亚-奥克塔维安·马诺拉切2023年5月2日阅读时间:10分钟

了解如何使用最好的 Selenium 浏览器绕过 Cloudflare 检测

了解如何使用最好的 Selenium 浏览器绕过 Cloudflare 检测

Cloudflare 是如何检测无头浏览器的?

Cloudflare 是一家拥有庞大网络的科技公司。他们专注于 CDN、DNS 以及各种在线安全系统等服务。其 Web 应用防火墙通常旨在防御 DDoS 或跨站脚本攻击等威胁。近年来,Cloudflare 及其他该领域的服务商纷纷引入了指纹识别系统,能够检测无头浏览器。正如您所料,Selenium 是首批受到这些技术影响的工具之一。 鉴于网络爬虫行业高度依赖这项技术,爬虫工具也因此受到了直接影响。

在探讨反机器人技术之前,我认为有必要先讨论一下 Cloudflare 是如何检测 Selenium 的。其实,这个系统可能非常复杂。例如,浏览器中存在一些 WebDriver 所不具备的属性。浏览器的 `navigator` 接口甚至有一个名为 `webdriver` 的属性,用于指示浏览器是否被自动化程序控制。而这正是最明显的破绽。如果你想亲自尝试一下:

  • 打开浏览器的开发者工具
  • 转到控制台
  • 输入以下命令:`navigator.webdriver`

就你的情况而言,它应该返回 `false`。但如果你用 Puppeteer 或 Selenium 尝试,结果会是 `true`。如果你想知道 Cloudflare 是如何利用这一点来检测机器人的,其实很简单。他们只需要在合作伙伴的网站上注入如下所示的脚本即可:

// detection-script.js

const webdriver = navigator.webdriver

// If webdriver returns true, display a reCaptcha

// In this example, I am transferring the user to a Cloudflare challenge page.

// But you get the idea

if ( webdriver ) location.replace('https://cloudflarechallenge.com')

当然,在现实中,这些服务商使用的检测层级远不止这些。就连屏幕尺寸、键盘布局,甚至是浏览器使用的插件,都会被用来对浏览器进行精准的指纹识别。如果你对无浏览器检测的工作原理感兴趣,可以看看我开发的这个简单的 Service Worker 测试工具。而这仅仅是针对浏览器的检测方式。 你还可以通过查看请求来源的 IP 地址来检测机器人活动。例如,如果你使用的是数据中心 IP,那么每次请求被封禁的概率都会增加。这就是为什么在构建网络爬虫时,建议使用家庭 IP 或 ISP 代理。

如何使用 Selenium 绕过 Cloudflare

幸运的是,网络爬虫社区非常活跃。正因为绕过 Cloudflare 及其他反机器人服务商的需求如此旺盛,该领域已涌现出许多开源解决方案。当编程社区通力合作时,定能成就非凡之事!展望未来,我建议我们按照以下步骤进行:

  • 进行一些测试,以确认默认的 Selenium 能否绕过 Cloudflare
  • 增加一些额外的规避措施,让我们的脚本更隐蔽

那么,让我们从第一步开始:

#1:默认的Selenium能否绕过Cloudflare?

我不是那种喜欢妄下结论的人。尤其是因为我们并不确切知道 Cloudflare 的系统是如何运作的。他们的代码采用了各种混淆手段,这使得逆向工程变得更加困难。正因如此,在我作为开发者的整个职业生涯中,我深知测试是理解系统运作原理的最佳途径。 那么,让我们构建一个基础的爬虫程序,看看它在受Cloudflare保护的真实目标上表现如何。

1.1. 配置环境

在 Python 中,最好将项目集中在一个目录下。因此,让我们创建一个新文件夹,打开终端窗口并切换到该目录:

# 创建一个新的虚拟环境并激活它

~ » python3 -m venv env && source env/bin/activate

# 安装依赖项

~ » python3 -m pip install selenium

# 创建一个新的 .py 文件,并在 IDE 中打开该项目

~ » touch app.py && code .

1.2. 使用 Selenium 构建一个简单的网页爬虫

既然你已经成功创建了项目,现在是时候添加一些代码了。我们这里不会构建什么复杂的东西,这个脚本仅用于测试。如果你想学习高级网页抓取技术,可以查看这篇关于 Pyppeteer 的教程 [链接]。

from selenium import webdriver

from selenium.webdriver.chrome.options import Options

# 将 Chrome 设置为无头模式

options = Options()

options.headless = True

# 创建一个新的 Chrome 实例并导航至目标页面

driver = webdriver.Chrome(options=options)

driver.get('https://www.snipesusa.com/')

# 等待页面加载

time.sleep(10)

# 截取页面截图

driver.get_screenshot_as_file('screenshot.png')

# 关闭浏览器

driver.quit()

现在请看这张截图。我得到的结果如下:

Snipes 网站上的防机器人验证界面,要求用户长按以确认自己是真人

我认为我们可以断定这次测试失败了。目标网站由 Cloudflare 提供保护,如你所见,我们的请求被拦截了。因此,默认情况下,Selenium 无法绕过 Cloudflare。我不会深入研究并测试其他机器人检测服务商。如果你想进一步测试,以下是一些目标网站及其服务商:

列出网站及其使用的机器人防护服务提供商的表格,例如 Kasada、Akamai、DataDome 和 Incapsula

#2:隐形 Selenium 能否绕过 Cloudflare?

首先,让我澄清一下术语。我所说的“隐形 Selenium”是指一种能够不被检测到并绕过 Cloudflare 的 Selenium 版本。 我这里指的并非任何具体的隐身技术。您可以通过几种方式在 Selenium 中实现规避技术。既有专门处理此功能的包,也可以使用 `execute_cdp_cmd` 直接与 Chrome API 交互。后者能提供更大的控制权,但需要更多的工作量。以下是一个示例,展示如何使用它来更改用户代理的值:

driver.execute_cdp_cmd('Emulation.setUserAgentOverride', {

               "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win32; x86) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.129 Safari/537.36",

               "platform": "Win32",

               "acceptLanguage":"ro-RO"

       })

但你必须通过CDP来查找那些能让你进行所有必要更改的 API。所以,目前我们先用一些包来测试一下吧。

1.1. 隐形 Selenium

至少有两个包可用于让 Selenium 隐身运行。但截至目前,尚无任何一个包能保证绕过 Cloudflare。因此,我们仍需进行测试,以验证它们是否有效。 首先,让我们来看看 `selenium-stealth`。该包是 `puppeteer-extra-plugin-stealth` 的封装,使得在 Python 的 Selenium 中也能使用 Puppeteer 的规避功能。要使用它,你需要先进行安装。打开终端窗口并输入以下命令:

# 安装 selenium-stealth

~ » python3 -m pip install selenium-stealth

现在一切就绪。我们可以利用它让之前的爬虫工具更隐蔽:

from selenium import webdriver

from selenium.webdriver.chrome.options import Options

from selenium_stealth import stealth

import time

# 将 Chrome 设置为无头模式

options = Options()

options.headless = True

# 创建一个新的 Chrome 实例

driver = webdriver.Chrome(options=options)

# 对 WebDriver 应用隐身设置

stealth(driver,

   languages=["en-US", "en"],

   vendor="Google Inc.",

   platform="Win32",

   webgl_vendor="Intel Inc.",

   renderer="Intel Iris OpenGL Engine",

   fix_hairline=True,

)

# 导航至目标页面

driver.get('https://www.snipesusa.com/')

# 等待页面加载

time.sleep(10)

# 截取页面截图

driver.get_screenshot_as_file('stealth.png')

# 关闭浏览器

driver.quit()

这次运行脚本时,我得到的结果与默认的Selenium设置有所不同:

Snipes 零售网站的截图,其中展示了 The North Face 的促销横幅

您可以使用的第二个选项是 `undetected_chromedriver`。该选项被描述为“经过优化的 Selenium Chromedriver”。让我们来试一试:

# 安装 undetected_chromedriver

~ » python3 -m pip install undetected_chromedriver

该代码与我们的默认脚本非常相似。主要区别在于包名。以下是一个使用 `undetected_chromedriver` 的基本爬虫,让我们看看它能否绕过 Cloudflare:

import undetected_chromedriver as uc

import time

# 将 Chrome 设置为无头模式

options = uc.ChromeOptions()

options.headless = True

# 创建一个新的 Chrome 实例并最大化窗口

driver = uc.Chrome(options=options, executable_path='/Applications/Google Chrome.app/Contents/MacOS/Google Chrome')

driver.maximize_window()

# 导航至目标页面

driver.get('https://www.snipesusa.com/')

# 等待页面加载

time.sleep(10)

# 截取页面截图

driver.get_screenshot_as_file('stealth-uc.png')

# 关闭浏览器

driver.quit()

然而,运行脚本的结果对我来说依然很顺利。看来至少这两个软件包能够成功绕过 Cloudflare 的防护。至少在短期内是这样。说实话,如果你频繁使用这些脚本,Cloudflare 很可能会追踪到你的 IP 地址并将其封禁。因此,让我向你介绍第三种方案:网络爬虫 API

1.2. Selenium 与 Web Scraping API

Web Scraping API 拥有一个名为“代理模式”的强大功能。您可以在此处了解更多相关信息。但我想特别指出的是,我们的代理模式可以与 Selenium 成功集成。这样,您就能使用我们已实现的所有规避功能。此外,我要告诉您,我们有一支专门的团队致力于开发定制化的规避技术。 从技术层面来说,我们处理 IP 轮换,使用多种代理,破解验证码,并利用 Chrome 的 API 持续更改我们的指纹。通俗来说,这意味着您将省去不少麻烦,并获得更高的成功率。您基本上将获得目前最隐蔽的 Selenium 版本。具体实现方法如下:

# 安装 selenium-wire

~ » python3 -m pip install selenium-wire

我们正在使用 `selenium-wire` 来通过代理运行 Selenium。以下是脚本:

from seleniumwire import webdriver

import time

# Method to encode parameters

def get_params(object):

   params = ''

   for key,value in object.items():

       if list(object).index(key) < len(object) - 1:

           params += f"{key}={value}."

       else:

           params += f"{key}={value}"

   return params

# Your WSA API key

API_KEY = '<YOUR_API_KEY>'

# Default proxy mode parameters

PARAMETERS = {

   "proxy_type":"datacenter",

   "device":"desktop",

   "render_js":1

}

# Set Selenium to use a proxy

options = {

   'proxy': {

       "http": f"http://webscrapingapi.{ get_params(PARAMETERS) }:{ API_KEY }@proxy.webscrapingapi.com:80",

   }

}

# Create a new Chrome instance

driver = webdriver.Chrome(seleniumwire_options=options)

# Navigate to target

driver.get('https://www.httpbin.org/get')

# Retrieve the HTML documeent from the page

html = driver.page_source

print(html)

# Close browser

driver.quit()

如果你运行这个脚本几次,就会发现 IP 地址每次都会发生变化。这就是我们的 IP 轮换系统。在后台,它还会自动应用一些规避技术。你甚至无需为此操心。我们会处理 Cloudflare 的绕过问题,这样你就可以更专注于数据解析。

结论

如果你想开发一个能够绕过 Cloudflare 的爬虫,就必须考虑诸多因素。即使由一支专职团队全天候运作,也无法保证规避措施每次都能奏效。这是因为,随着每个浏览器版本的发布,API 都有可能新增功能。而其中一些功能可能会被用于识别和检测机器人。

我甚至要说,要绕过 Cloudflare 和其他服务商,最好的浏览器就是你自己搭建的那个。我们在 Web Scraping API 搭建了一个,现在与大家分享。祝您刮取愉快!

关于作者
Mihnea-Octavian Manolache,全栈开发工程师 @ WebScrapingAPI
米赫内亚-奥克塔维安-马诺拉什全栈开发工程师

Mihnea-Octavian Manolache 是 WebScrapingAPI 的全栈及 DevOps 工程师,负责开发产品功能并维护确保平台平稳运行的基础设施。

开始构建

准备好扩展您的数据收集规模了吗?

加入2,000多家企业,使用WebScrapingAPI在无需任何基础设施开销的情况下,以企业级规模提取网页数据。