【爬虫】Linux上使用selenium + chrome + xvfb 实现无界面的网页截图

前言


本问介绍一种在无桌面(无 X server)的linux系统下,不用打开浏览器就可以完成网页页面截图的方法,之前多数用的是PhantomJS + Selenium的方法,但是我使用 PhantomJS + Selenium 时报错:

Selenium support for PhantomJS has been deprecated, please use
headless

原来是二者已分手,我们只能使用另一种方法,提供一个虚拟的界面。


安装xvfb以及pyvirtualdisplay


xvfb概述

X server是linux系统里面图形接口服务器的简称。windows系统的界面是这个系统不可分割的一部分,各种窗口操作界面显示都是由系统核心直接管理的,而linux的图形界面并比较常见的linux界面操作环境有KDE和GNOME,为它们提供系统支持的就是X server,而并非linux核心。

xvfb就是这么一个提供虚拟界面的工具, 这个工具相当于一个wrapper, 给应用程序提供虚拟的 X server(X server是Linux系统里面图形接口服务器的简称,常见的有KDE和GNOME)。

总结一句话就是 xvfb可以理解为虚拟的 linux界面,可以供应用程序使用。

安装xvfb

在ubuntu16.04系统下,使用如下命令安装

sudo apt-get install xvfb

验证使用

Xvfb :99 -ac 2>/dev/null &
export DISPLAY=:99   

firefox

安装pyvirtualdisplay

pyvirtualdisplay 是Xvfb 的python封装

pip install pyvirtualdisplay 



安装chrome, chromedriver和selenium


安装selenium

pip install selenium

安装chrome

1、安装依赖包:

  sudo apt-get install libxss1 libappindicator1 libindicator7

2、下载安装包:

wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb

3、执行dpkg安装方式

sudo dpkg -i google-chrome-stable_current_amd64.deb 

4、卸载chrome

之前安装chrome后发现版本和chromedriver没对上,可以选择修改其中任一版本,如果需要卸载,则可以用这个命令:

sudo apt-get remove google-chrome-stable

安装chrome driver

1、下载安装包

cd /usr/software

wget -N http://chromedriver.storage.googleapis.com/2.26/chromedriver_linux64.zip

因为版本问题,最好手动下载一个zip格式的安装包,并上传到服务器:

在淘宝镜像手动下载对应上一步chrome版本的chromedriver

淘宝镜像: https://npm.taobao.org/mirrors/chromedriver/

下载后放入服务器的 /usr/software 路径下

2、安装解压缩工具unzip

sudo apt-get install unzip

如果出错可能需要修复 apt 工具

apt --fix-broken install

3、解压缩+赋予可执行的权限

unzip chromedriver_linux64.zip
chmod +x chromedriver

4、移动

# mv -f : 强行覆盖 
sudo mv -f chromedriver /usr/local/share/chromedriver

5、建立软连接

sudo ln -s /usr/local/share/chromedriver /usr/local/bin/chromedriver
 
sudo ln -s /usr/local/share/chromedriver /usr/bin/chromedriver

6、验证chromedriver是否安装成功:

chromedriver --version



实践


不用实际打开浏览器的方式进行页面截图:

from pyvirtualdisplay import Display
from selenium import webdriver
import time
from selenium.webdriver.chrome.options import Options

display = Display(visible=0, size=(1600, 900))
display.start()
chrome_options = Options()
chrome_options.add_argument('--no-sandbox')
chrome_options.add_argument('--disable-dev-shm-usage')
chrome_options.add_argument('--headless')
chrome_options.add_argument('--disable-gpu')

driver = webdriver.Chrome(chrome_options=chrome_options)
url = "https://news.qq.com/a/20190626/003510.htm"
driver.get(url)
driver.save_screenshot(driver.title + “png”)
print (driver.title)
driver.quit()     
print("end with quit")

chrome_options说明

chrome_options.add_argument(’–no-sandbox’)
chrome_options.add_argument(’–disable-dev-shm-usage’)
chrome_options.add_argument(’–headless’) #无头启动浏览器
chrome_options.add_argument(’–disable-gpu’) #禁止使用硬件加速

chrome_options.add_argument(‘blink-settings=imagesEnabled=false’)

如果用来爬虫,还可以设置不加载图片等方法来进一步提高打开页面速度

截整个页面

有些网页内容很多,滚动条比较长,如果我们需要截这种页面的全部内容的话,就需要知道这个页面的实际高度和宽度,根据一个页面的所有内容都在body中的情况,我们可以转换思路为通过selenium获得这个页面的body的长度和宽度

from pyvirtualdisplay import Display
from selenium import webdriver
import time

from selenium.webdriver.chrome.options import Options

display = Display(visible=0)
display.start()
chrome_options = Options()
chrome_options.add_argument('--no-sandbox')
chrome_options.add_argument('--disable-dev-shm-usage')
chrome_options.add_argument('--headless')
#chrome_options.add_argument('blink-settings=imagesEnabled=false')
chrome_options.add_argument('--disable-gpu')

driver = webdriver.Chrome(chrome_options=chrome_options)
driver.set_window_size(1028,3210) 

url = "https://news.qq.com/a/20190626/003510.htm"
driver.get(url)

body_element = driver.find_elements_by_tag_name('body')
body_height = body_element[0].size.get('height')
body_width = body_element[0].size.get('width')
if body_height and body_width and int(body_height) > 0 and int(body_width) > 0:
    print("set_window_size")
    driver.set_window_size(int( body_width),int(body_height))
    print(body_height,body_width)
imgpath = driver.title[:5]  + ".png"
driver.save_screenshot(imgpath)
print(imgpath)
#driver.get_screenshot_as_file(imgpath)
print (driver.title)
driver.quit()     
print("end with quit")

网页截图中文显示为方框

原因:ubuntu系统中缺少支持的中文字体。

解决方案:

1、下载任意一款中文字体(ttf格式的字体),我选择的是simsun.ttc ,也就是宋体

2、将该字体文件放入/usr/share/fonts/路径下

3、依次执行如下命令使字体生效:

mkfontdir
mkfontscale
fc-cache -fv     #(最重要)

4、通过命令 fc-list :lang=zh 查看当前系统中支持中文的字体,如果出现simsun.ttc,则说明该字体已生效,再截图就会看到中文咯!

你可能感兴趣的:(【爬虫】)