最近在工作中使用headless chrome写了不少东西,本文吐槽一下它目前存在的一些问题。
linux环境下不能直接运行
headless chrome在mac表现十分完美,然而在linux上环境下就十分残废了:
- centos7.1
- 对不起,我尽力了但还是没跑起来
- centos 7.3
yum install pango.x86_64 libXcomposite.x86_64 libXcursor.x86_64 libXdamage.x86_64 libXext.x86_64 libXi.x86_64 libXtst.x86_64 cups-libs.x86_64 libXScrnSaver.x86_64 libXrandr.x86_64 GConf2.x86_64 alsa-lib.x86_64 atk.x86_64 gtk3.x86_64 ipa-gothic-fonts xorg-x11-fonts-100dpi xorg-x11-fonts-75dpi xorg-x11-utils xorg-x11-fonts-cyrillic xorg-x11-fonts-Type1 xorg-x11-fonts-misc -y
- centos7.4
- yum install {{如上的依赖包}} && yum update
可以看到, headless chrome在linux完全不是npm install --save puppeteer
就能用的,想把headless chrome的代码部署到生产环境实在是太难了,对于无法自定义docker的平台来说也等于是没法用。这个是headless chrome目前最大的问题。
headless chrome本身太大
headless chrome的npm包实在是太大了,仅仅npm install一下就有70MB以上,会严重拖慢docker部署的效率,更有甚者,一些docker把部署包限制得比70MB还小,干脆就部署不了了(说的就是阿里云)
不过,headless chrome支持连接远程实例,并且可以通过PUPPETEER_SKIP_CHROMIUM_DOWNLOAD
环境变量来跳过安装chrome包,因此如果提前构建好一个远程实例集群的话,效果是相当不错的。
不支持在iframe中进行操作
就是这么尴尬,现在博主是手动使用去除cors的浏览器参数去操作iframe中的dom,然而这样用过的人都知道它有个严重的缺点:iframe的dom挂载出来的时间太慢了,经常是肉眼可见iframe中的内容已经加载好,但是要等五六秒才能拿到iframe中的dom
不支持select操作
https://github.com/GoogleChrome/puppeteer/pull/779 PR已提交,等着合并就好
资源占用太大
以4c8g的2017版mbp来说,同时开3个headless chrome就能跑满cpu,同时开10个headless chrome能把负载跑到20+。也就是说,一台正常的生产服务器,基本也只能保证一核对应一个headless chrome浏览器实例,不提升单浏览器中任务的并行程度的话,资源消耗实在是太大了。
目前社区有一个提案,允许新建页面时指定context以避免session共享必须新开一个headless chrome,但headless chrome官方并没有回应,毕竟这个提案涉及到chrome本身,而不是headless chrome这一套开发者工具协议套件自己。
不支持连接和断开钩子
由于headless chrome在linux上的较差的维护性,管理headless chrome实例就顺理成章了。需要注意的是,目前没有任何钩子函数可以在用户远程连接headless chrome以及断开这两个时间点触发,因此必须做一层代理,并且是一层websocket代理。
没有鉴权
连接远程实例时,headless chrome目前没有任何权限验证,任何人只要拿到了websocket链接就可以直接连上。此时,代理层就显得越发重要了。
最后
虽然本文吐槽了headless chrome的许多问题,但博主还是得说清楚,headless chrome实际上是用代码来操作chrome浏览器,因此它的行为和手动访问是差不多的,目前我爬取了上百个网站,没有一个网站能够识别出这是一个爬虫(当然除了有验证码的页面)。
也就是说,headless chrome特别适合流量不大但反爬虫非常厉害的网站,以及UI自动化集成测试。