Firefox替换Phantomjs抓取/测试方案

之前写爬虫抓取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后会自动设置闲置的号码,起始是99xvfb-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

参考: