当前位置: 首页 > 编程日记 > 正文

服务端如何识别是selenium在访问以及解决方案参考二

有不少朋友在开发爬虫的过程中喜欢使用Selenium + Chromedriver,以为这样就能做到不被网站的反爬虫机制发现。

先不说淘宝这种基于用户行为的反爬虫策略,仅仅是一个普通的小网站,使用一行Javascript代码,就能轻轻松松识别你是否使用了Selenium + Chromedriver模拟浏览器。

我们来看一个例子。

使用下面这一段代码启动Chrome窗口:

from selenium.webdriver import Chromedriver = Chrome()

现在,在这个窗口中打开开发者工具,并定位到Console选项卡,如下图所示。

现在,在这个窗口输入如下的js代码并按下回车键:

window.navigator.webdriver

可以看到,开发者工具返回了true。如下图所示。

但是,如果你打开一个普通的Chrome窗口,执行相同的命令,可以发现这行代码的返回值为undefined,如下图所示。

所以,如果网站通过js代码获取这个参数,返回值为undefined说明是正常的浏览器,返回true说明用的是Selenium模拟浏览器。一抓一个准。这里给出一个检测Selenium的js代码例子:

webdriver = window.navigator.webdriver;
if(webdriver){console.log('你这个傻逼你以为使用Selenium模拟浏览器就可以了?')
} else {console.log('正常浏览器')
}

网站只要在页面加载的时候运行这个js代码,就可以识别访问者是不是用的Selenium模拟浏览器。如果是,就禁止访问或者触发其他反爬虫的机制。

那么对于这种情况,在爬虫开发的过程中如何防止这个参数告诉网站你在模拟浏览器呢?

可能有一些会js的朋友觉得可以通过覆盖这个参数从而隐藏自己,但实际上这个值是不能被覆盖的:

对js更精通的朋友,可能会使用下面这一段代码来实现:

Object.defineProperties(navigator, {webdriver:{get:()=>undefined}});

运行效果如下图所示:

确实修改成功了。这种写法就万无一失了吗?并不是这样的,如果此时你在模拟浏览器中通过点击链接、输入网址进入另一个页面,或者开启新的窗口,你会发现,window.navigator.webdriver又变成了true。如下图所示。

那么是不是可以在每一个页面都打开以后,再次通过webdriver执行上面的js代码,从而实现在每个页面都把window.navigator.webdriver设置为undefined呢?也不行。

因为当你执行:driver.get(网址)的时候,浏览器会打开网站,加载页面并运行网站自带的js代码。所以在你重设window.navigator.webdriver之前,实际上网站早就已经知道你是模拟浏览器了。

接下来,又有朋友提出,可以通过编写Chrome插件来解决这个问题,让插件里面的js代码在网站自带的所有js代码之前执行。

这样做当然可以,不过有更简单的办法,只需要设置Chromedriver的启动参数即可解决问题。

在启动Chromedriver之前,为Chrome开启实验性功能参数excludeSwitches,它的值为['enable-automation'],完整代码如下:

from selenium.webdriver import Chrome
from selenium.webdriver import ChromeOptionsoption = ChromeOptions()
option.add_experimental_option('excludeSwitches', ['enable-automation'])
driver = Chrome(options=option)

此时启动的Chrome窗口,在右上角会弹出一个提示,不用管它,不要点击停用按钮。

再次在开发者工具的Console选项卡中查询window.navigator.webdriver,可以发现这个值已经自动变成undefined了。并且无论你打开新的网页,开启新的窗口还是点击链接进入其他页面,都不会让它变成true。运行效果如下图所示。

本文转载自:https://www.kingname.info/2019/02/12/hide-webdriver/

转载于:https://www.cnblogs.com/chenyibai/p/10610127.html

相关文章:

LSM 优化系列(二)-- dCompaction: Speeding up Compaction of the LSM-Tree via Delayed Compaction

文章目录背景描述dCompaction设计触发条件 VCT触发VT 合并的条件 VSMT测试数据优化的重心集中在减少写放大上,同时将读性能维持在和rocksdb 原生读性能接近,优化思想是中国科学院的2位博士 提出的。论文原地址:dCompaction: Speeding up Comp…

Android应用系列:完美运行GIF格式的ImageView(附源码)

前言 我们都知道ImageView是不能完美加载Gif格式的图片,如果我们在ImageView中src指定的资源是gif格式的话,我们将会惊喜的发觉画面永远停留在第一帧,也就是不会有动画效果。当然,经过略加改造,我们是可以让gif在Image…

wordpress怎么修改html,WordPress后台编辑器HTML模式界面中添加修改删除按钮

在WordPress编辑器HTML模式界面中添加按钮一文中,我大致介绍了怎么在后台添加一些自定义的按钮,本文则更为详细全面的对wordpress后台编辑器HTML模式下的按钮自定义进行详解,以让开发者肆意的修改按钮及其布局。自定义按钮起效的两种途径 ↑首…

OCA读书笔记(9) - 管理数据同步

9.Managing Data Concurrency 描述锁机制以及oracle如何管理数据一致性监控和解决锁冲突 管理数据的并发--管理锁数据的不一致:脏读更改丢失幻影读 脏读:数据是指事务T2修改某一数据,并将其写回磁盘,事务T1读取同一数据后,T2由于某…

Java EE学习笔记(四)

Spring的数据库开发 1、Spring JDBC 1)、Spring JDBC模块的作用:Spring的JDBC模块负责数据库资源管理和错误处理,大大简化了开发人员对数据库的操作,使得开发人员可以从繁琐的数据库操作中解脱出来,从而将更多的精力投入到编写业务…

SpringBoot 中实现订单30分钟自动取消的策略

在电商和其他涉及到在线支付的应用中,通常需要实现一个功能:如果用户在生成订单后的一定时间内未完成支付,系统将自动取消该订单。本文将详细介绍基于Spring Boot框架实现订单30分钟内未支付自动取消的几种方案,并提供实例代码。

一键部署 SpringCloud 微服务,这套流程值得学习一波儿!

一键部署 springcloud 微服务,需要用到 Jenkins K8S Docker等工具。本文使用jenkins部署,流程如下图开发者将代码push到git运维人员通过jenkins部署,自动到git上pull代码通过maven构建代码将maven构建后的jar打包成docker镜像 并 push docker镜像到docker registry通过k8s发起 发布/更新 服务 操作其中 2~5步骤都会在jenkins中进行操作。

Rocksdb 的 rate_limiter实现 -- compaction限速

文章目录前言1. Compaction为什么会影响Client qps1.1 基本LSM介绍1.2 LSM internal ops1.3 长尾延时的原因2. Rate limiter 基本限速接口3. Rate Limiter 限速原理实现3.1 Rate Limiter的传入3.2 Rate Limiter 控制 sync datablock的速率3.3 Rate Limiter控制写入速率4. rocks…

Oracle --获取绑定变量的值.

SELECT * FROM DBA_HIST_SQLBIND WHERE SNAP_ID>67073 AND SNAP_ID<67079 AND SQL_ID3DR3410F086P4;SELECT * FROM v$sql_bind_capture where sql_id http://blog.itpub.net/22034023/viewspace-689802/ 通过v$sql_bind_capture视图&#xff0c;可以查看绑定变量&#xf…

计算机网络TCP/IP协议-从双绞线到TCP

消息响应也是同理,这种带端口的消息发送方式,其实就是UDP协议,UDP简单粗暴,但是UDP存在很多问题,所以我们需要设计一个稳定可靠的协议,TCP协议,首先,网络是不稳定的,我们发送的消息很有可能会在中途丢失,所以需要设置重试机制,当消息发送失败时重新发送,为了判断是否成功,还需要要求接收方收到消息后,必须发送确认消息,这样就可以保证消息必达,另外大段的内容发送,很容易造成部分丢失,导致全部内容都要重新发送,于是我们可以将数据分包,分成多个包发送。到这,也行你会发现了,演示中的IP地址是怎么设置的呢?

使用HTML CSS完成初步的页面,任务九:使用HTML/CSS实现一个复杂页面(示例代码)

任务目的通过实现一个较为复杂的页面&#xff0c;加深对于HTML&#xff0c;CSS的实战能力实践代码的复用、优化任务描述整个页面内容宽度固定&#xff0c;但头部的蓝色导航和浏览器宽度保持一致任务注意事项只需要完成HTML&#xff0c;CSS代码编写&#xff0c;不需要写JavaScri…

Yii-yiic使用

原文在&#xff1a;http://blog.sina.com.cn/s/blog_862b12fb0101n00v.htmlyii提供了强大的命令行工具来快速的创建相关组件和应用。下面就来讲解用yiic工具快速创建yii应用我的web目录在d:\ EasyPHP-DevServer\data\localweb下&#xff1b;yiiframework在D:\EasyPHP-DevServer…

nginx语法

一、 1. 配置文件由指令与指令块构成&#xff1b; 2. 每条指令以&#xff1b;分号结尾&#xff0c;指令与参数间以空格符号分隔&#xff1b; 3. 指令块以{} 大括号将多条指令组在一起&#xff1b; 4. include语句允许组合多个配置文件以提升可维护性&#xff1b; 5. 使用#符号添…

如何对 Rocksdb以及类似存储引擎社区 提出 有效的性能问题?

性能 是rocksdb的优点&#xff0c;活跃的社区十分欢迎大家对各自使用rocksdb 过程中性能相关的疑惑点进行提问。提问的时候如果能够提供更多&#xff0c;更详细的信息 是可以增加快速得到恢复回复的概率。当然&#xff0c;性能是一个非常广泛且有巨量影响因素的话题&#xff0c…

我已经喜欢上了Python

早就听说了Python语言&#xff0c;今天试了试&#xff0c;挺喜欢她了。 Python 3.4.2 (v3.4.2:ab2c023a9432, Oct 6 2014, 22:15:05) [MSC v.1600 32 bit (Intel)] on win32Type "copyright", "credits" or "license()" for more information.&g…

layui跳转html如何带参数,Layui跳转页面代码(可携带复杂参数)

今天用了Layui的“数据表格 - 数据操作”示例代码&#xff0c;结果发现点击“编辑”按钮出出来一个弹出消息框&#xff0c;效果如下&#xff1a;虽然说也可以用“弹出层”做编辑页面&#xff0c;但是&#xff0c;由于我编辑的东西很多&#xff0c;用“弹出层”不太理想。我就想…

java获取日期

/* * 获取昨天日期 方法一&#xff0c;这个方法好像有点慢 */Date dt new Date(); Calendar cal Calendar.getInstance();cal.add(Calendar.DATE, -1);time new SimpleDateFormat( "yyyy-MM-dd").format(cal.getTime()); /* * 获取昨天日期 方法二 */Date as ne…

DRF (Django REST framework) 中的视图类

视图说明 1. 两个基类 1&#xff09;APIView rest_framework.views.APIView APIView是REST framework提供的所有视图的基类&#xff0c;继承自Django的View父类。 APIView与View的不同之处在于&#xff1a; 传入到视图方法中的是REST framework的Request对象&#xff0c;而不是…

Go:分布式学习利器(1) -- 开发环境搭建 + 运行第一个go程序

文章目录为什么要学习 go开发环境搭建 -- MAC运行第一个go程序go 函数的返回值设置go 函数的命令行参数为什么要学习 go 在如下几个应用场景的需求下产生了go: 超大规模分布式计算集群多核硬件的架构web模式下的大规模开发和频繁的进度更新 所以go 语言有如下几个特点&#…

html生成的超级链接预览功能,超链接特效

功能说明超链接特效功能是基于报表特殊效果功能的一种扩展实现。报表特殊效果功能的作用是为单元格添加一些特殊的显示效果。超链接特效可以给超链接添加特殊显示效果&#xff0c;实现超链接功能的扩展增强。当产品默认生成的超链接显示效果不能满足用户的个性化需求时&#xf…

ROOT android 原理。 基于(zergRush)

出自&#xff1a; http://bbs.gfan.com/android-2996211-1-1.html 须要ROOT的同学请去上面的地址下载。 a.控制手机创建个暂时目录,然后把zergRush脚本写入此目录,并改动此文件权限使之能够运行(这一步无需ROOT权限); adb shell rm -r /data/local/tmpadb shell mkdir /data/lo…

Oracle数据库日常维护知识总结

DBA要定时对数据库的连接情况进行检查&#xff0c;看与数据库建立的会话数目是不是正常&#xff0c;如果建立了过多的连接&#xff0c;会消耗数据库的资源。同时&#xff0c;对一些“挂死”的连接&#xff0c;可能会需要DBA手工进行清理。首先要说的是&#xff0c;不同版本数据…

JAVA 第五周学习总结

20175304 2018-2019-2 《Java程序设计》第五周学习总结 教材学习内容总结 Java为什么要定义接口&#xff1a;接口的作用是实现多重继承&#xff0c;因为一个子类只能继承一个父类&#xff0c;但是可以实现一个或多个接口。使用关键字interface来定义一个接口&#xff0c;定义方…

Go: 分布式学习利器(2)-- Go中的变量,常量 以及与其他语言变量之间的差异

文章目录1. Go 语言编写测试代码2. Go 的变量3. Go 常量定义1. Go 语言编写测试代码 源码文件以 _test结尾&#xff1a; xxx_test.go测试方法名需以Test开头&#xff1a; func TESTXXX(t *testing.T) {..} &#xff0c;且参数列表直接用go 默认的test参数即可 如下first_test…

Scala:Functions and Closures

1 object Functions {2 def main(args: Array[String]) {3 // 本地函数4 def localFun(msg: String) println(msg)5 localFun("Hi")6 7 // 函数对象8 var list List(1, 2, 3)9 list.foreach((x: Int) > println(x)) 10 list.fore…

云计算机机房怎么样,如何知道云电脑配置多少?怎么选择云电脑机房?

一般在玩一款游戏时&#xff0c;需要考虑玩游戏的配置&#xff0c;云电脑帮助我们实现配置的需求&#xff0c;那如何才能知道云电脑配置是多少&#xff0c;该怎么选择云电脑机房。在使用云电脑时&#xff0c;我们不用考虑自己的手机、平板和电脑的硬件&#xff0c;只要设备能正…

eclipse中新建android项目,不自动生成R.java

http://huyuantai000.iteye.com/blog/1681582转载于:https://www.cnblogs.com/wmm3416/p/3386698.html

获取子iframe的属性

第一种方法&#xff1a; <iframe name"iframeName" src"http://www.test.com"></iframe> // name"iframeName" 取值 window.frames[iframeName] 第二种方法&#xff1a; <iframe id"iframeId" src"http://www.t…

Go: 分布式学习利器(3) -- Go的数据类型和运算符

文章目录1. Go的数据类型1.1 类型转化1.2 类型的预定义1.3 指针类型2. Go 的运算符1. Go的数据类型 GO的基本数据类型如下&#xff1a; bool string int int8 int16 int32 int64 uint uint8 uint16 uint32 uint64 uintptr byte // 基本和uint8 类型一样 rune // 代表unicode …

云职教课堂计算机文化基础,2020智慧职教云课堂计算机文化基础答案最新最全单元测试答案...

参考答案如下智慧职教最新最全【判断题】两种气体在相同温度下放入同一个容器中,测得的压强分别为 和 ,则把它们同时放入容器中后的总压强为 .云课【单选题】根据物质的导电能力,将物质分为哪些类别?A. 导体 B. 半导体 C. 绝缘体 D. 以上都对堂计【单选题】按照数的进位制概念…