之前写爬虫抓取js动态渲染网页的时候使用过Phanomjs这个无界面浏览器。详见:《使用Python+selenium+Phantom.js爬取js加载数据的网页》,Linux下除了需要自己编译Phantomjs外,也没什么麻烦的,而且几个月前QT的BUG现在也已经修复了。按照官方的以来说明来编译只要配置不是太差的机器,应该都没什么问题。如今发现一个更加完美的方案,就是在服务器端使用虚拟显示器和火狐浏览器,记录如下
xvfb是一个虚拟显示器,下面是来自wiki的解释
Xvfb or X virtual framebuffer is a display server implementing the X11 display server protocol. In contrast to other display servers, Xvfb performs all graphical operations in memory without showing any screen output.
安装软件及依赖包
dnf install xorg-x11-server-Xvfb
dnf install firefox
pip install selenium
pip install pyvirtualdisplay
测试程序
#!/bin/env python
from pyvirtualdisplay import Display
from selenium import webdriver
with Display(visible=0, size=(800, 600)):
browser = webdriver.Firefox()
browser.get('http://www.google.com')
print browser.title
browser.quit()
输出
Google
介绍完毕,如果想了解更多,请继续阅读
- 上边的测试程序visible参数: True -> Xephyr, False -> Xvfb
- pyvirtualdisplay是一个封装了Xvfb, Xephyr and Xvnc操作的工具包
文档:
简单介绍下Xvfb的参数
Xvfb :1 -screen 0 1600x1200x32 The server will listen for connections as server number 1, and screen 0 will be depth 32 1600x1200. Xvfb :1 -screen 1 1600x1200x16 The server will listen for connections as server number 1, will have the default screen configuration (one screen, 1280x1024x8), and screen 1 will be depth 16 1600x1200.
:1
就是服务编号,后边的screen后的数字就是显示器编号
举个栗子,我们在后台开启一个Xvfb的服务
Xvfb :1 -screen 1 1600x1200x16 &
看一下后台的进程,确实存在一个3188端口的进程来提供服务
[root@the5 ~]# ps -aux | grep Xvfb
root 3188 0.0 4.0 182788 20424 pts/0 S 17:15 0:00 Xvfb :1 -screen 1 1600x1200x16
root 3572 0.0 0.4 11240 2240 pts/0 S+ 17:44 0:00 grep --color=auto Xvfb
现在,我也不知道怎么去使用这个已经创建了的程序,有兴趣的朋友自己研究下,接下来介绍一个基于Xvfb的小工具xvfb-run
,有了这个东西,操作起来就方便多了。
先写一个display.sh脚本,以便测试
[root@the5 ~]# cat display.sh
#!/bin/env bash
echo $DISPLAY
这个脚本的作用就是输出环境变量DISPLAY
的值
[root@the5 ~]# bash display.sh
[root@the5 ~]# xvfb-run --server-num=1 bash display.sh
:1
/usr/bin/xvfb-run: line 171: kill: (3640) - No such process
[root@the5 ~]# xvfb-run --auto-servernum --server-args="-screen 1 1600x1200x16" bash display.sh
:99
在xvfb-run指定server-num号的时候,它会使用之前使用Xvfb创建的服务,在使用--auto-servernum
后会自动设置闲置的号码,起始是99
,xvfb-run
在运行后会删除虚拟显示服务
修改文章头部的python代码如下,使用xvfb-run
来运行代码,其效果是一样的
#!/bin/env python
from selenium import webdriver
driver = webdriver.Firefox()
driver.get("http://www.google.com")
title = driver.title
print title
driver.quit()
[root@the5 ~]# xvfb-run --auto-servernum --server-args="-screen 1 1600x1200x16" python test.py
Google
现在应该清晰了,Xvfb提供虚拟显示服务,xvfb-run提供了封装,可以自动的构建删除服务,并且可以在创建的虚拟显示器中运行我们的程序,同样的,不同的语言下,大多都有基于Xvfb的包,比如上面介绍的python包pyvirtualdisplay,更多可以翻看上边的文档
使用xvfb-run和cutycapt截图
大多数的Linux发行版的包管理器应该都能直接安装cutycapt,值得说明的是Fedora下cutycapt的包名是CutyCapt
,并且安装后的软件名称也是CutyCapt
不经验证是否可行就转载的人是不对的
网上的截图命令都是这样格式的:
xvfb-run --auto-servernum --server-args="-screen 0 1366x768x24" CutyCapt --url=http://www.google.com --out=google-1366x768.png
如上命令可以使用,不过分辨率大小并不是设定的值。CutyCapt这个软件不会根据xvfb-run设定的显示器大小来截图。
正确的截图姿势是设置最小宽高
xvfb-run CutyCapt --min-width=1366 --min-height=768 --url=http://www.google.com --out=google-1366x768.png
输出如果提示:
libEGL warning: DRI2: failed to open swrast (search paths /usr/lib64/dri)
那么安装mesa-dri-drivers包可以解决
[root@the5 ~]# dnf search mesa-dri-drivers
Last metadata expiration check performed 1:34:04 ago on Thu Mar 31 15:36:53 2016.
======================================== N/S Matched: mesa-dri-drivers ========================================
mesa-dri-drivers.i686 : Mesa-based DRI drivers
mesa-dri-drivers.x86_64 : Mesa-based DRI drivers
[root@the5 ~]# dnf install mesa-dri-drivers
参考:
- 《How do I run Selenium in Xvfb?》
- 《How to install and configure Xvfb in Linux/Centos》
- 《How To Run Your Tests Headlessly with Xvfb》
- 《Selenium Headless Firefox WebDriver using PyVirtualDisplay》
- 《Headless Browser Testing With Xvfb》
- 《How to take higher resolution screenshots with CutyCapt》
- 《如何在Linux上将HTML页面转化成png图片》