selenium chrome 服务器资源优化方向

一直在服务器上运行selenium + chromedriver 方式做爬虫, 发现服务器的负载居高不下, 优化了几次supervisor的进程数, 也没有好转......

最近还发现chrome进程又残余....服务器不卡才怪咧....


一怒之下查看了selenium的源码, 找解决办法....


seleniumwire webdriver

我使用的是seleniumwire, 这个第三方包是基于selenium二次封装, 增加了许多实用的功能,  

1) 简单地为chrome浏览器配置代理  (简直是爬虫党的福音, 不过你不嫌麻烦可以在脚本中每次都安装代理插件....)

2) 捕捉所有的请求, 有点像中间人攻击的味道, 用途挺多, 可以改header, 过滤request, 吧啦吧啦......

那么, 我们就首先看看seleniumwire的源码吧....看他究竟做了些什么鬼


seleniumwire里的chrome类

先看初始化方法__init__,  先是调用了一个create_proxy的方法, 哦, 可能有的小伙伴会问这事什么意思, 英语菜不能怪我啊~

就是创建代理, 步入方法里看看呗....


创建代理的方法


创建代理的关键代码

原理是在本地创建了一个代理服务, 把所有请求都转发到我们作为初始化方法参数传进去的代理, 简单说就是二级代理, 


传入代理的形式

来到这里, 差不多就可以知道代码作者的意图了, 就是通过在本地搭建一个http代理服务,来实现真正代理的转发和中间人的作用

回到初始化方法, 最后调用了父类的初始化方法


调用父类初始化方法

那么他的父类是谁呢?


父类

一番追溯, 果然还是selenium中的chrome driver 类, 兜兜转转还是回来了....

那我们也看一下他的初始化方法吧


父类的初始化方法

果然发现有坑!!!!!!!!!!!!!!!!!

前边的逻辑就是加载各种chrome的配置, 后边每实例化一个chrome webdriver实例, 都会开启一个与之对应的driver服务....

来到这里, 我又想起一句最近很火的歌词,   小朋友, 你是否有很多问号?????

这里我安利另一篇我个人觉得写得不错的文章  https://www.jianshu.com/p/195ff63921de


webdriver原理

这个webdriber服务, 就是将我们在python脚本中调用的selenium方法, 转化为对chrome浏览器的操作

下面举个例子,  例如我们在脚本调用了 driver.get(url), 使用浏览器访问一个url网址


driver get()

调用了execute方法执行了与之对应的command


get对应的command

进入execute方法看下:


分析webdriver的execute方法, 

延伸一下session_id, 效果就是打开了一个浏览器,  是在webdirver类的初始化方法创建的....没留意到的人请自觉点赞......


初始化方法调用start_session创建session_id

言归正传, 继续深入, 看command_executor的execute方法, 


RemoteConnection类

RemoteConnection这个类才是归根到底, 是如何去发http请求driver服务,最终转化为操作浏览器命令的所在

看下边的命令, 是不是有点头绪了呢...


command


command_executor的execute方法

至此我也是刚发现, 原来调用selenium中的很多方法都是有返回值的, 就是driver服务的响应内容

跑题了!!! 回到最初....说了辣么多, 大概都懂了吧

优化方向就有了,  原先是每个实例开启一个driver服务, 改进为多个实例共用一个driver服务,

是否可行??? 官方文档都建议共用一个driver服务

看了官方文档案例用的是Remote的链接方式,其好处是每次启动chromedriver,都是通过remote的方式去连接到共用的chromedriver(开放9515端

口),这样子能够节省很多服务器的资源;而直接用webserver.Chrome的方式连接chromedriver

开始改造: 为了不影响源码, 我把selenium chrome webdriver 的类复制一份, 单独拿来修改,


改造方法

改完啦, 看懂一两天, 改造一分钟,   这就完事了, 真短~~~~(我说的是时间)

ok 在本地开启9515的driver服务 , 试下运行测试脚本, 脚本中记得要引入的是我们自己改造的类, 不是selenium的原始类


本地开启9515的driver服务


有这句输出证明我们使用改造好的类, 再用ps查看 chromedirver相关进程, 一直只有一个9515端口的进程,

改造成功!!!!!!!!!!!!!!!!!!!!!!撒花

有个东西注意一下, quit方法在退出的时候要把self.seriver的相关操作注释掉, 否则会报错


quit方法注意修改

ps -ef|grep chrome|wc -l  查看一下chrome的进程, 比之前少了很多很多, 嗨心~~~~~

最后埋个坑给大家:

造成chrome残余进程的一个原因, 在driver实例化的时候失败, 最后不能调用quit方法退出

有能解决的大佬评论一下


driver实例化失败

百度一下查到了可能的原因, 


异常原因

可能是代理商服务器压力太大, 主动关闭了一些tcp链接.....这可坑了我~~~~

好了, 写得不怎么样, 有问题有建议可以评论留言....

赛有拉拉

你可能感兴趣的:(selenium chrome 服务器资源优化方向)