【问题标题】:What is the difference in accessing Cloudflare website using ChromeDriver/Chrome in normal/headless mode through Selenium Python通过 Selenium Python 在正常/无头模式下使用 ChromeDriver/Chrome 访问 Cloudflare 网站有什么区别
【发布时间】:2020-03-29 04:33:13
【问题描述】:

我对 Python Selenium for 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有什么区别?

【问题讨论】:

    标签: python selenium selenium-chromedriver cloudflare google-chrome-headless


    【解决方案1】:

    我拿走了你的代码,去掉了可选的arguments并添加了一些arguments来执行测试,如下:

    • 代码块:

      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()
      
    • 控制台输出:

      <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 参数可以清楚地看到您正在访问的页面:

    • 标题为:访问被拒绝 | www.manta.com 使用 Cloudflare 限制访问
    • 一些信息:发生了什么?该网站正在使用安全服务来保护自己免受在线攻击。

    结论

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


    结尾

    您可以在以下位置找到一些相关讨论:

    【讨论】:

    • options.add_argument("--headless") 没有这个参数在我这边一切正常,那么为什么--headless 会生成Cloudflare 保护警报呢?代码中的所有相同只有一个参数......有什么办法可以避免它吗?像平常一样使用--headless吗?
    • @МаксимДихтярь 查看更新的答案并让我知道状态。
    • 你没有回答问题,为什么被屏蔽了?
    • @Guy 也许您需要重新审视答案,特别是分析结论部分。
    • @DebanjanB 我做到了。分析部分在问题中,只是不是html格式。结论是正确的,但没有解释为什么没有--headless 就可以工作。
    【解决方案2】:

    Cloudflare 旨在阻止机器人。他们假设数据抓取工具使用无头浏览器,因此他们阻止了它。来自 Cloudflare What is Data Scraping?

    *无头浏览器是一种网络浏览器,很像 Chrome 或 Firefox,但默认情况下它没有可视化用户界面, 允许它比典型的网络浏览器移动得更快。经过 本质上在命令行级别运行,无头浏览器 能够避免渲染整个 Web 应用程序。数据刮板 编写使用无头浏览器更快地请求数据的机器人,例如 没有人查看被抓取的每个页面。

    【讨论】:

    • 阻止机器人不限于 Cloudflare。这是众多反报废网站的常见做法。除了 Cloudflare,还有 Distil、Akmai 等
    • @DebanjanB 我说它是 Cloudflare 独有的吗? OP 询问了受 Cloudflare 保护的特定站点。
    【解决方案3】:

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

    <?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.36 vs Mozilla/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":{}}} vs {}
    • Javascript window.navigator.mimeTypes: {"0":{},"1":{},"2":{},"3":{}} vs {}
    • Javascript window.outerWidth: 1367 vs 0
    • Javascript window.outerHeight: 641 vs 0

    注意:在您发布的 Python 脚本中,您缺少几行,以删除 window.webdriver 属性(没有这个,服务器检测到您正在使用 WebDriver 是微不足道的)[ref]:

    driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {
        "source": """
        Object.defineProperty(navigator, 'webdriver', {
          get: () => undefined
        })
      """
    })
    

    【讨论】:

      【解决方案4】:

      这是 Cloudflare 不喜欢的 HTTP User-Agent 标头。

      要解决此问题,只需更改您的 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")
      

      【讨论】:

        【解决方案5】:

        在抓取受 CloudFlare 保护的网站时,您需要执行以下操作:

        1. 确保您发送的标头与浏览器发送的标头相同(并且顺序相同)
        2. 确保您使用的是非数据中心 IP 地址范围
        3. 如果它仍然不起作用,就像我的情况一样......

        我在抓取一个电子商务网站(guess dot com)时遇到了同样的问题。更改标题顺序并没有为我解决。我的结论:显然,CloudFlare 分析请求的 TLS 指纹并抛出 403 (1020) 代码,以防指纹与通常用于抓取的 node.js/python/curl 匹配。解决方案是模拟一些流行浏览器的指纹——最明显的方法是使用 Puppeteer.js 和 puppeteer 额外的隐身插件。它奏效了!但是..由于 Puppeteer 对我的用例来说不够快(我说得委婉些.. Puppeteer 在资源和迟缓方面很疯狂)我不得不构建一个使用无聊SSL(Chrome 使用的 SSL 库)的实用程序 - 因为编译 C/C++ 代码并找出某些 TLS 库的隐蔽编译错误对于大多数 Web 开发人员来说并不有趣 - 我将其包装为 API 服务器,您可以在这里尝试:https://rapidapi.com/restyler/api/scrapeninja

        详细了解 CloudFlare 如何分析 TLS: https://blog.cloudflare.com/monsters-in-the-middleboxes/

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-04-14
          • 2019-12-06
          • 2019-05-13
          • 1970-01-01
          • 1970-01-01
          • 2019-08-12
          • 1970-01-01
          相关资源
          最近更新 更多