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

分步指南:如何绕过 Cloudflare 并提升网页抓取效果

分步指南:如何绕过 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 构建一个简单的网页爬虫

既然你已经成功创建了项目,现在是时候添加一些代码了。我们不会在这里构建什么复杂的东西。我们只需要这个脚本用于测试。如果你想了解高级爬取技术,请查看这个 [链接](此处应插入文章) 教程。

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()

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

机器人检测页面提示用户长按以确认自己是真人

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

列出目标网站及其机器人防护服务提供商的表格,包括Kasada和Akamai

#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 网站首页横幅展示了一位身穿北面夹克的模特

您可以使用的第二个选项是 `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在无需任何基础设施开销的情况下,以企业级规模提取网页数据。