• 移除Selenium中的 window.navigator.webdriver


    《一日一技:如何正确移除Selenium中window.navigator.webdriver的值》一文中,我们介绍了在当时能够正确从Selenium启动的Chrome浏览器中移除window.navigator.webdriver的方法。

    后来时过境迁,Chrome升级了版本,导致当时的方法已经失效。如下图所示:

    在这里插入图片描述

    针对最新版本的Chrome,我们应该如何正确隐藏这个参数呢?

    在那篇文章里面,我骂了一种掩耳盗铃的方式:

    打开网页,然后通过执行如下 JavaScript语句来隐藏window.navigator.webdriver的值:

    Object.defineProperty(navigator, 'webdriver', {
          get: () => undefined
        })
     

     

    我骂了这种方式为掩耳盗铃,是因为他们是在网页已经加载完毕以后才运行这段 JavaScript 代码的,可此时网站自身的 js 程序早就已经通过读取window.navigator.webdriver知道你现在使用模拟浏览器,你隐藏了又有什么用呢?

    所以即使要执行这段 JavaScript 语句,也应该是在浏览器运行网站自带的所有 JavaScript 之前。

    这也就是我们现在的方案。

    可能有读者会认为,是不是通过写 Chrome 浏览器的插件,让插件里面的 JavaScript 语句在网站页面刚刚打开,还没有运行自带的 JavaScript 之前运行。

    这种方式虽然可以解决问题,但稍显麻烦,我们今天的方法非常简单。就是使用 Google 的Chrome Devtools-Protocol(Chrome 开发工具协议)简称CDP。

    我们打开 CPD 的官方文档[1],可以看到如下的命令:
    在这里插入图片描述

    “在每个Frame 刚刚打开,还没有运行 Frame 的脚本前,运行给定的脚本。”

    通过这个命令,我们可以给定一段 JavaScript 代码,让 Chrome 刚刚打开每一个页面,还没有运行网站自带的 JavaScript代码时,就先执行我们给定的这段代码。

    那么如何在 Selenium中调用 CDP的命令呢?实际上非常简单,我们使用driver.execute_cdp_cmd。根据 Selenium 的官方文档[2],传入需要调用的 CDP 命令和参数即可:
    在这里插入图片描述

    于是我们可以写出如下代码:

    from selenium.webdriver import Chrome
    
    driver = Chrome('./chromedriver')
    driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {
      "source": """
        Object.defineProperty(navigator, 'webdriver', {
          get: () => undefined
        })
      """
    })
    driver.get('http://exercise.kingname.info')
     
    运行效果如下图所示:

    在这里插入图片描述

    完美隐藏window.navigator.webdriver。并且,关键语句:

    driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {
      "source": """
        Object.defineProperty(navigator, 'webdriver', {
          get: () => undefined
        })
      """
    })
     
    只需要执行一次,之后只要你不关闭这个driver开启的窗口,无论你打开多少个网址,他都会自动提前在网站自带的所有 js 之前执行这个语句,隐藏window.navigator.webdriver

    如果有人运行上面的代码,出现如下报错:
    在这里插入图片描述

    那么请升级你的 ChromeDriver。老版本的 Chrome + ChromeDriver只能用以前的方法,不能用今天的方法。新版本的 Chrome + ChromeDriver可以使用今天的方法,但不能用老方法。正应了那句话:

    “上帝给你关上一扇门的时候,悄悄为你开了一扇窗。”

    虽然使用以上代码就可以达到目的了,不过为了实现更好的隐藏效果,大家也可以继续加入两个实验选项:

    from selenium import webdriver
    options = webdriver.ChromeOptions()
    options.add_experimental_option("excludeSwitches", ["enable-automation"])
    options.add_experimental_option('useAutomationExtension', False)
    driver = webdriver.Chrome(options=options, executable_path='./chromedriver')
    driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {
      "source": """
        Object.defineProperty(navigator, 'webdriver', {
          get: () => undefined
        })
      """
    })
    driver.get('http://exercise.kingname.info')
     

     

     

    参考资料

    [1] CPD 的官方文档: https://chromedevtools.github.io/devtools-protocol/tot/Page#method-addScriptToEvaluateOnNewDocument

    [2]
    官方文档: https://www.selenium.dev/selenium/docs/api/py/webdriver_chrome/selenium.webdriver.chrome.webdriver.html#selenium.webdriver.chrome.webdriver.WebDriver.execute_cdp_cmd

    参考文献:

    来源青南大佬:
    (最新版)如何正确移除Selenium中的 window.navigator.webdriver
    一日一技:如何正确移除Selenium中window.navigator.webdriver的值

    转:

    https://blog.csdn.net/weixin_41173374/article/details/104686243

  • 相关阅读:
    pug 基础篇
    胡里胡哨-老师改卷纸
    javaScript 原生技巧
    angular9的学习(十二)插槽
    typescript高级编程(二)
    typescript高级编程(一)
    ActiveMq 使用指北
    基于ZooKeeper的分布式锁实现
    windows下配置启动脚本并设置开机自启及相应关闭脚本
    腾讯位置服务JavaScript API GL实现文本标记的碰撞避让
  • 原文地址:https://www.cnblogs.com/presleyren/p/12936553.html
Copyright © 2020-2023  润新知