使用Selenium Python通过ChromeDriver/Chrome正常模式或无头模式访问Cloudflare网站有什么区别?

10

我对Python Selenium中Chrome浏览器的--headless模式有一个问题。

代码

 from selenium import webdriver
 from selenium.webdriver.common.desired_capabilities import DesiredCapabilities

 CHROME_DRIVER_DIR = "selenium/chromedriver"

 chrome_options = webdriver.ChromeOptions()
 caps = DesiredCapabilities().CHROME
 chrome_options.add_argument("--disable-dev-shm-usage")
 chrome_options.add_argument("--remote-debugging-port=9222")
 chrome_options.add_argument("--headless")  # Runs Chrome in headless mode.
 chrome_options.add_argument('--no-sandbox')  # # Bypass OS security model
 chrome_options.add_argument("--disable-extensions")
 chrome_options.add_argument("--disable-gpu")

 browser = webdriver.Chrome(desired_capabilities=caps, executable_path=CHROME_DRIVER_DIR, options=chrome_options)

 browser.get("https://www.manta.com/c/mm2956g/mashuda-contractors")
 print(browser.page_source)
 browser.quit()

当我删除chrome_options.add_argument("--headless")时,一切都很顺利,但是在添加了--headless*后就出现了以下问题

Please enable cookies.

Error 1020 Ray ID: 53fd62b4087d8116 • 2019-12-04 11:19:28 UTC

Access denied

What happened?
This website is using a security service to protect itself from online attacks.

Cloudflare Ray ID: 53fd62b4087d8116 • Your IP: 168.81.117.111 • Performance & security by Cloudflare

正常模式和--headless模式有什么区别?

4个回答

11

是HTTP User-Agent头让Cloudflare不喜欢。

为了解决这个问题,只需更改您的user-agent Chrome选项(以下代码适用于Python中的Selenium):

option.add_argument('--headless')
option.add_argument("user-agent=Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.125 Safari/537.36")

似乎无法工作 - 2022年3月 - user7660047

6

我使用了这个服务器端脚本进行测试:

<?php
echo "<pre><code>";
var_dump($_SERVER);
echo "</code></pre>";
?>
<script>
    var el = document.getElementsByTagName('code')[0];
    for(var prop in window.navigator){
        var str = JSON.stringify(window.navigator[prop])
        el.innerHTML = el.innerHTML + "window.navigator." + prop + " = " + str + "\n";
    }
    var skip_props = ['parent', 'top', 'frames', 'self', 'window'];
    for(var prop in window){
        if (skip_props.indexOf(prop) > -1) { continue; }
        el.innerHTML = el.innerHTML + "window." + prop + " = ";
        var str = JSON.stringify(window[prop])
        el.innerHTML = el.innerHTML + str + "\n";
    }
</script>

我使用ChromeDriver加载了此页面,有使用--headless和没有使用这个参数两种情况,并使用print(driver.find_element_by_tag_name('code').text)打印输出。然后我对比了这两个输出。
以下是我发现的差异:
  • HTTP Accept-Language 头部:en-US,en;q=0.9en-US
  • HTTP User-Agent 头部:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/83.0.4103.61 Safari/537.36(请注意第二个字符串中的HeadlessChrome提及)
  • Javascript window.navigator.plugins{"0":{"0":{}},"1":{"0":{}},"2":{"0":{},"1":{}}}{}
  • Javascript window.navigator.mimeTypes{"0":{},"1":{},"2":{},"3":{}}{}
  • Javascript window.outerWidth13670
  • Javascript window.outerHeight6410
值得注意的是,在您发布的Python脚本中,您漏掉了一些代码行以去除window.webdriver属性(如果没有此代码,服务器可以轻松检测到您正在使用WebDriver)[参考]:
driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {
    "source": """
    Object.defineProperty(navigator, 'webdriver', {
      get: () => undefined
    })
  """
})

2
Cloudflare旨在阻止机器人。他们认为数据爬取者使用无头浏览器,因此他们正在阻止它。无头浏览器是一种Web浏览器,类似于Chrome或Firefox,但默认情况下没有可视用户界面,使其比典型的Web浏览器快得多。通过基本上在命令行级别运行,无头浏览器能够避免渲染整个Web应用程序。数据爬取者编写的机器人使用无头浏览器更快地请求数据,因为没有人查看每个被抓取的页面。来源:Cloudflare 什么是数据爬取?

阻止机器人的行为不仅限于 Cloudflare。这是许多反扒网站的常见做法。除了 Cloudflare,还有 Distil、Akmai 等。 - undetected Selenium
2
@DebanjanB 我说过这只是Cloudflare的特有功能吗?OP询问的是由Cloudflare保护的特定网站。 - Guy

2

我拿了你的代码,去掉了可选的参数,并添加了一些参数以执行以下测试:

  • Code Block:

    from selenium import webdriver
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support.ui import WebDriverWait
    from selenium.webdriver.support import expected_conditions as EC
    
    options = webdriver.ChromeOptions() 
    options.add_argument("start-maximized")
    options.add_argument("--headless")
    options.add_experimental_option("excludeSwitches", ["enable-automation"])
    options.add_experimental_option('useAutomationExtension', False)
    driver = webdriver.Chrome(options=options, executable_path=r'C:\Utility\BrowserDrivers\chromedriver.exe')
    driver.get("https://www.manta.com/c/mm2956g/mashuda-contractors")
    print(driver.page_source)
    driver.quit()
    
  • Console Output:

    <html class="js" lang="en-US" style="opacity: 1; visibility: visible;"><!--<![endif]--><head>
    <title>Access denied | www.manta.com used Cloudflare to restrict access</title>
    <meta charset="UTF-8">
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1">
    <meta name="robots" content="noindex, nofollow">
    <meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1">
    <link rel="stylesheet" id="cf_styles-css" href="/cdn-cgi/styles/cf.errors.css" type="text/css" media="screen,projection">
    <!--[if lt IE 9]><link rel="stylesheet" id='cf_styles-ie-css' href="/cdn-cgi/styles/cf.errors.ie.css" type="text/css" media="screen,projection" /><![endif]-->
    <style type="text/css">body{margin:0;padding:0}</style>
    
    
    <!--[if gte IE 10]><!--><script type="text/javascript" src="/cdn-cgi/scripts/zepto.min.js"></script><!--<![endif]-->
    <!--[if gte IE 10]><!--><script type="text/javascript" src="/cdn-cgi/scripts/cf.common.js"></script><!--<![endif]-->
    
    
    
    </head>
    <body>
      <div id="cf-wrapper">
        <div class="cf-alert cf-alert-error cf-cookie-error" id="cookie-alert" data-translate="enable_cookies">Please enable cookies.</div>
        <div id="cf-error-details" class="cf-error-details-wrapper">
          <div class="cf-wrapper cf-header cf-error-overview">
        <h1>
          <span class="cf-error-type" data-translate="error">Error</span>
          <span class="cf-error-code">1020</span>
          <small class="heading-ray-id">Ray ID: 53fd7c2fca12d5fc • 2019-12-04 11:36:52 UTC</small>
        </h1>
        <h2 class="cf-subheadline">Access denied</h2>
          </div><!-- /.header -->
    
          <section></section><!-- spacer -->
    
          <div class="cf-section cf-wrapper">
        <div class="cf-columns two">
          <div class="cf-column">
            <h2 data-translate="what_happened">What happened?</h2>
            <p>This website is using a security service to protect itself from online attacks.</p>
          </div>
    
    
        </div>
          </div><!-- /.section -->
    
          <div class="cf-error-footer cf-wrapper">
      <p>
        <span class="cf-footer-item">Cloudflare Ray ID: <strong>53fd7c2fca12d5fc</strong></span>
        <span class="cf-footer-separator"></span>
        <span class="cf-footer-item"><span>Your IP</span>: 123.201.54.43</span>
        <span class="cf-footer-separator"></span>
        <span class="cf-footer-item"><span>Performance &amp; security by</span> <a href="https://www.cloudflare.com/5xx-error-landing?utm_source=error_footer" id="brand_link" target="_blank">Cloudflare</a></span>
    
      </p>
    </div><!-- /.error-footer -->
    
    
        </div><!-- /#cf-error-details -->
      </div><!-- /#cf-wrapper -->
    
      <script type="text/javascript">
      window._cf_translation = {};
    
    
    </script>
    
    
    
    </body></html>
    

分析

从提取的页面源代码可以清楚地看到,使用--headless参数进入的页面是这样的:

  • 标题为:Access denied | www.manta.com used Cloudflare to restrict access
  • 一些信息为:What happened?: This website is using a security service to protect itself from online attacks.

结论

浏览上下文,即Chrome浏览器会话被检测为BOT,导航被阻止


结束语

您可以在以下几个相关讨论中找到相关内容:


options.add_argument("--headless") 如果不加这个参数,我的程序一切正常,为什么加上 --headless 会触发 Cloudflare 的保护警报呢?代码中只有一个参数,为什么会出现这种情况?有没有什么方法可以避免这种情况?能否像正常模式一样使用 --headless 参数? - Максим Дихтярь
@МаксимДихтярь,请查看更新后的答案并告诉我状态。 - undetected Selenium
你没有回答这个问题,为什么它被阻止了? - Guy
@Guy 或许你需要重新查看答案,特别是其中的 分析结论 部分。 - undetected Selenium
2
@DebanjanB 我看过了,分析部分在问题中,只是不以html格式呈现。结论是正确的,但没有解释为什么可以在不使用“--headless”的情况下运行。 - Guy
@Guy 你仍然需要详细阅读我在“结论”部分提供的讨论,以便更好地理解。 - undetected Selenium

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接