早先用Docker在云服务器上搭了一个《Selenium 执行环境》,可以通过将脚本上传至服务器上,让服务器自动挂机执行。一夜爬遍某乎也不是梦了(还不用担心妈妈让我关电脑了)。
但是这套环境有个最大的问题,脚本怎么上传呢?紧接着还有一个更大的问题,上传之后怎么自动触发执行呢?为了上传文件这么一件小事,难道还得搞个Apache?那多麻烦呀,而且我那朵小云可只有1核2G呢。还是想个更轻量的解决方案吧。
参考目标网站
相信不少人都接触过【菜鸟教程】或【W3C School】这样的良心网站,他们提供了很多语言的学习教程,同时还提供了在线编程的功能,即允许用户通过网页的方式执行一段代码。比如这样的:
假如我的小云也有这样一个环境,那么是不是就可以通过前端页面直接将脚本交给后端执行了呀,重要的是这样上班摸鱼也不会被发现了。完美!
前端
当然我不用像前辈做得那样复杂,能有语法高亮显示,能传给后端,能回显执行结果就好了。说干就干,当然动手之前还是好好学习下前辈的代码吧,免得走弯路不是。通过简单浏览了前辈前端代码,发现一个关键字CodeMirror,再进一步搜索了一下,发现这家伙不得了,功能强到不行,关键还开源。相关的介绍这里就不展开了,网上一搜一大把的资源,点击这里可以跳转至CodeMirror官网。简单来说有了这位大哥的支持,满足我那一丁点的前端诉求,不要太方便了哦。参考官网的指导,我的小云很快速的上线了一个看上去还凑合的前端页面。
为了方便在触摸设备上编辑,还多增加了全屏控制开关(电脑上支持F11快捷进入)。并且还会预先填入初始化脚本(脚本来源于《自动刷新Gitee》一文),减少重复输入。
后端
CodeMirror只负责前端的显示,并不提供实际执行功能,如何将代码用云端的环境执行起来着实让人头疼,难道还是避免不了要开发一个后台服务吗?唉,虽说一个后台服务难度不大,可我实在不想把简单的事搞这么复杂呀(最重要的是懒)。为了躲避开发的工作,我也想了很多方案。
- 方案一:个人网盘方案
很早我就在小云上部署了一套NextCloud作为个人网盘,而NextCloud提供多种语言的API接口,允许用户通过接口直接管理文件,这其中就有文件上传。那么这套方案我设想的工作流是:
这套方案存在两处硬伤,首先通过JS保存文件需要得到用户的许可,从安全角度讲浏览器是不允许JS私自向存储器写文件的。其次NextCloud提供的API当中并没有类似钩子一样的函数,允许我们对上传的文件做处理(当然也可能是我不知道而已),因此该方案不可行。不过也多亏这个方案让我明确了我能操作的一定只有CodeMirror能提供的Blob数据而已。
- 方案二:轻量级PUT/POST服务器
这套方案需要我能提供一个支持PUT/POST的web服务,因为前端需要将文件数据传到后端那么可以参考表单提交的方式传递数据,虽说GET也能实现同样的效果,但毕竟不符合语法约定。这套方案需要后端提供具备以下功能:
- 轻量级的HTTP服务,如:Tomcat、Apache2、Nginx、IIS等,虽然这其中并不是所有都配得上轻量这个称号。
- 接口响应程序,这没有现成的,不过有很多开发框架可以使用如:Spring、Spring boot、Spring cloud、Servlet、PHP等等。
当前已部署有Nginx作为网关,将不同地址分发到不同的Docker上去,因此第一点满足。Gitee上也有几年前基于Spring cloud做的文件上传代码(良好上库习惯的优势),做些调整应该能很快上线,第二点也满足。可是该方案不符合我当前做个人网站的原则(优选现成方案,次选简单方案,最差才是自己动手)。
- 方案三:WebSocket实时连接
就在我一筹莫展,在网上闲逛的时候,在一个不起眼的角落发现了一个名叫WebSocket的东西,进而在阮大佬的WebSocket 教程中大致了解到这玩意可以像Socket一样让前后端建立长连接。哎,这就有意思了。如果能像实时聊天一样将前端的BLOB传给后端,后端处理后再将结果回传给前端,那不就可以实现远程执行脚本了吗?而且看上去好像还挺简单的,那就说干就干吧。
实现
其实要做很简单,之前不是已经搭建好Selenium Docker环境了吗?只需要在其基础上加上websocketd即可。
codeonline:
image: selenium-py
command: ./websocketd --ssl --sslcert=/var/www/s
l/code.pem --sslkey=/var/www/ssl/code.key bash code/
run.sh
restart: always
volumes:
- /home/core/projects/websocketd/release/websoc
ketd:/var/wss/websocketd
- /home/core/data/codeonline/run.sh:/var/wss/co
de/run.sh
- /home/core/data/codeonline/script:/var/wss/co
de/script
- /home/core/data/codeonline/tmp:/var/wss/code
tmp
- /home/core/data/www/ssl/:/var/www/ssl
networks:
- netwss
depends_on:
- chrome
chrome:
image: selenium/standalone-chrome
container_name: chrome
volumes:
- /dev/shm:/dev/shm
networks:
- netwss
在原来的基础上加了一些映射关系,而最重要的是Docker启动后会执行Websocketd。
websocketd --ssl --sslcert=/var/www/s l/code.pem --sslkey=/var/www/ssl/code.key bash code/run.sh
通过加载SSL证书,开启WSS协议。并且由run.sh接受客户端发来的消息。而为了调试,run.sh只做一件事儿,那就是回显客户端发来的消息。
while read MSG; do echo $MSG
这样就打通了前端与后端的双向数据通道,并且几乎零开发工作量(前端基于bootstrap4 可快速完成自适应布局页面)。后面会再讲到如何将前端的BLOB真正的执行起来,今天就先到这里吧。