24

Headless Chrome and API | nmask's Blog

 4 years ago
source link: https://thief.one/2018/03/06/1/?
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
我已爬遍了全世界,而你却迟迟不见

  自从Google在chrome59版本后加入了 Headless Chrome,类似phantomjs、selenium等工具作者都放弃了维护自身的产品(原因可参考文章 QtWebkit or Headless Chrome)。因此作为使用者的我们也是时候放弃phantomjs,转而研究Headless Chrome了。由于网上对于Headless Chrome的资料还很少,因此我先收集整理一波,随后慢慢学习研究,渐渐将本篇内容补充完善。

Headless Chrome 介绍

headless chrome意思是无头chrome浏览器,相对于传统的chrome浏览器,这是一个可以在后台用命令行操作浏览器的工具,对于爬虫编写以及web自动化测试都有很大的作用。相比较同类工具Phantomjs,其更加强大(主要因为其依赖的webkit更新)。

Headless Chrome 安装

目前只支持mac与linux系统,需要下载chrome浏览器并安装。

mac install headless chrome

mac下直接去官网下载安装包即可,mac下chrome浏览器位置,为了方便使用,用alias别名启动。

alias chrome="/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome"
alias chrome-canary="/Applications/Google\ Chrome\ Canary.app/Contents/MacOS/Google\ Chrome\ Canary"
alias chromium="/Applications/Chromium.app/Contents/MacOS/Chromium"

下载chrome-canary

说明:Mac 和 Linux 上的 Chrome 59 都可以运行无需显示模式。对 Windows 的支持将在 Chrome 60 中提供。要检查你使用的 Chrome 版本,请在浏览器中打开 chrome://version。

linux install headless chrome

vim /etc/yum.repos.d/chrome.repo
写入以下内容:
[google-chrome]
name=google-chrome
baseurl=http://dl.google.com/linux/chrome/rpm/stable/$basearch
enabled=1
gpgcheck=0
gpgkey=https://dl-ssl.google.com/linux/linux_signing_key.pub



yum install -y google-chrome-stable

测试运行:

google-chrome --headless --print-to-pdf https://thief.one

报错处理:

Running as root without --no-sandbox is not supported # 错误信息

解析方案:

vim /opt/google/chrome/google-chrome
找到 exec -a "$0" "$HERE/chrome" "$@"
改为 exec -a "$0" "$HERE/chrome" "$@" --user-data-dir --no-sandbox

说明:若在安装过程中报错,则将源文件中的gpgcheck改为0

linux安装headless chrome参考:http://akai-tsuki.hatenablog.com/entry/2017/06/18/000000

Headless Chrome 基础用法

HELP信息:

chrome \
--headless \ # Runs Chrome in headless mode.
--disable-gpu \ # Temporarily needed for now.
--remote-debugging-address=127.0.0.1
--remote-debugging-port=9222 \
https://thief.one # URL to open. Defaults to about:blank.

访问一个网页获取源码

–dump-dom 标志将打印 document.body.innerHTML 到标准输出:

chrome --headless --disable-gpu --dump-dom https://thief.one/

访问一个网页将源码创建成一个PDF

–print-to-pdf 标志将页面转出为 PDF 文件:

chrome --headless --disable-gpu --print-to-pdf https://thief.one/

访问一个网页并截图

使用–screenshot标志运行 Headless Chrome 将在当前工作目录中生成一个名为 screenshot.png的文件:

chrome --headless --disable-gpu --screenshot https://thief.one/
# 设置图片大小
chrome --headless --disable-gpu --screenshot --window-size=1280,1696 https://thief.one/

访问一个网页并进行js交互(REPL模式)

–repl 标志可以使 Headless Chrome 运行在一个你可以使用浏览器评估 JS 表达式的模式下。执行下面的命令:

chrome --headless --disable-gpu --repl https://thief.one
>>> location.href
{"result":{"type":"string","value":"https://thief.one"}}
>>> quit

启动一个监听端口

chrome --remote-debugging-port=9222 --remote-debugging-address=0.0.0.0

可以通过浏览器打开:http://0.0.0.0:9222

Headless Chrome API

以上演示了使用命令行的方式操作headless chrome,那么怎么在代码中使用它呢?
api工具如下:
官方:puppeteer
底层:chrome-remote-interface
活跃:chromeless
非官方:headless-chrome-crawler

Python相关的API:
pychrome
Pyppeteer 推荐
chromote
chrome_remote_interface_python

puppeteer 介绍

Puppeteer 是一个由 Chrome 团队开发的 Node 库。它提供了一个高层次的 API 来控制无需显示版(或 完全版)的 Chrome。它与其他自动化测试库,如 Phantom 和 NightmareJS 相类似,但是只适用于最新版本的 Chrome。

puppeteer 安装

mkdir puppeteer_test # 创建一个项目目录
cd puppeteer_test
npm init
npm i --save puppeteer

安装puppeteer前需要在系统上安装nodejs与npm;安装完puppeteer,默认会自动安装最新版本的chromium。
注意:系统默认安装的npm与nodejs版本都很低,而使用puppeteer需要node6.4.0+,async/await需要node7.6.0+,因此建议安装node7.6.0版本,否则会导致无法使用。

安装升级nodejs与npm

要安装puppeteer,需要先安装npm与nodejs,而puppeteer对nodejs版本有要求,因此不能用系统默认安装的nodejs版本。

wget http://nodejs.org/dist/v7.6.0/node-v7.6.0-linux-x64.tar.gz
tar -zvxf node-v7.6.0-linux-x64.tar.gz

共享至全局

rm -rf /usr/bin/node /usr/bin/npm
ln -s /path/node-v7.6.0-linux-x64/bin/node /usr/bin/node
ln -s /path/node-v7.6.0-linux-x64/bin/npm /usr/bin/npm

若用yum安装过nodejs,需要移除其他版本:

yum remove npm
yum remove nodejs

查看nodejs与npm版本:

node -v
npm -v

安装升级nodejs过程参考:http://jeeinn.com/2017/02/236/

puppeteer 使用

在使用puppeteer前,先要确定puppeteer、nodejs、npm安装成功(版本正确),且headless chrome安装成功。
官方API文档:https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md

打印用户代理:

在puppeteer_test目录下创建一个example1.js文件,写入:

const puppeteer = require('puppeteer');
(async() => {
const browser = await puppeteer.launch({
headless: true,
args: ['--no-sandbox', '--disable-setuid-sandbox'],
console.log(await browser.version());
browser.close();
})();

运行代码:

node example1.js
获取页面的屏幕截图:

创建一个example2.js文件,写入:

const puppeteer = require('puppeteer');
(async() => {
const browser = await puppeteer.launch({
headless: true,
args: ['--no-sandbox', '--disable-setuid-sandbox'],
const page = await browser.newPage();
await page.goto('https://thief.one', {waitUntil: 'networkidle2'});
await page.pdf({path: 'screen.pdf', format: 'A4'});
browser.close();
})();

运行代码:

node example2.js

说明:在运行puppeteer之前不需要额外开启一个headless-chrome进程,因为其本身就会去开启。

发送POST请求获取源码
const puppeteer = require('puppeteer');
puppeteer.launch({headless: true,args: ['--no-sandbox', '--disable-setuid-sandbox'],}).then(async browser => {
const page = await browser.newPage();
await page.setRequestInterception(true); // 开启请求捕捉
page.on('request', interceptedRequest => {
const overrides = {};
//console.log(interceptedRequest.url()); // 输出捕捉到的请求URL
if (interceptedRequest.url()=='http://127.0.0.1:8000/'){
overrides.method = 'POST';
overrides.postData = '{"id":"2"}';
interceptedRequest.continue(overrides); // 重放
await page.goto('http://127.0.0.1:8000/');
await console.log(await page.content()); // 输出源码
await browser.close();
安装puppeteer报错

在linux下安装puppeteer报错,即:

npm i --save puppeteer 命令没有运行成功

失败原因可能是linux版本不支持,centos7下成功,centos6下测试失败。

运行puppeteer报错处理

报错如下,说明代码语法有问题,或者node版本太低,不符合要求:

SyntaxError: Unexpected token function

报错如下,说明代码中需要设置headless状态为true

Failed to launch chrome

解决方案,修改代码为如下:

const browser = await puppeteer.launch({
headless: true,
args: ['--no-sandbox', '--disable-setuid-sandbox'],

报错如下,与上面解决方案一致:

1025/084740.006078:ERROR:zygote_host_impl_linux.cc(88)] Running as root without --no-sandbox is not supported. See https://crbug.com/638180.

pyppeteer

pyppeteer模版是对puppeteer的python封装,因为puppeteer是用nodejs写的,所以要在python中使用得用pyppeteer模块。

pyppeteer安装

pyppeteer模版只支持python3.5以上版本。

python3 -m pip install pyppeteer
pyppeteer简单的例子
import asyncio
from pyppeteer import launch
async def main():
browser = await launch(args=['--no-sandbox'])
page = await browser.newPage()
await page.goto('http://example.com')
await page.screenshot({'path': 'example.png'})
await browser.close()
asyncio.get_event_loop().run_until_complete(main())

说明:在使用pyppeteer时,不需要额外开启headless-chrome进程(与puppeteer一样)。更多pyppeteer模版使用方法,参考:https://miyakogi.github.io/pyppeteer/reference.html#page-class

pyppeteer报错处理

错误类似如下:

pyppeteer.errors.BrowserError: Failed to connect to browser port: http://127.0.0.1:58871/json/version

解决方案:

加上:args=['--no-sandbox'],同puppeteer类似。
browser = await launch(args=['--no-sandbox'])

chrome-remote-interface工具

可以用来分析渲染一个页面过程中所有的请求过程,包括获取所有的请求接口以及响应内容等。再运行chrome-remote-interface代码前,需要先启动headless chrome进程,即:

chrome --headless --remote-debugging-port=9222

安装chrome-remote-interface:

npm install chrome-remote-interface

然后编写代码:(以获取所有请求url为例)

const CDP = require('chrome-remote-interface');
// node nmask.js https://nmask.cn
var options = process.argv;
var target_url = options[2];
CDP((client) => {
// extract domains
const {Network, Page} = client;
// setup handlers
Network.requestWillBeSent((params) => {
console.log(params.request.url);
Page.loadEventFired(() => {
client.close();
// enable events then start!
Promise.all([
Network.enable(),
Page.enable()
]).then(() => {
return Page.navigate({url: target_url});//输出请求的url
}).catch((err) => {
console.error(err);
client.close();
}).on('error', (err) => {
console.error(err);

运行这段代码:

node nmask.js https://thief.one

chromeless介绍

chromeless社区比较火热,代码更新也非常频繁,个人比较看好。

chromeless安装

chromeless对nodejs版本要求是>8.2(centos7下node7.6测试可以),因此需要先升级nodejs,升级方法参考前文;升级完以后,再安装chromeless项目环境。

mkdir chromeless_test
cd chromeless_test
npm init
npm install chromeless

chromeless使用

官方API文档:https://github.com/graphcool/chromeless/blob/master/docs/api.md#api-goto
在线代码运行环境:https://chromeless.netlify.com

创建chromeless_test.js,写入:

const { Chromeless } = require('chromeless')
async function run() {
const chromeless = new Chromeless()
const screenshot = await chromeless
.goto('https://www.baidu.com')
//.type('chromeless', 'input[name="q"]')
//.press(13)
//.wait('#resultStats')
.screenshot()
console.log(screenshot) // prints local file path or S3 url
await chromeless.end()
run().catch(console.error.bind(console))

运行代码:

nohup google-chrome --headless --remote-debugging-port=9222 & #开启本地headless chrome
node chromeless_test.js

注意:在运行chromeless前,需要先安装headless chrome,并且需要在本地开启--remote-debugging-port=9222,监听本地9222端口;chromeless也支持使用远程的headless chrome

pychrome工具

暂没有研究,尽情期待!

Linux截图中文字体变方块如何解决?

出现这类问题主要是因为linux服务器字体缺失的问题,解决方案是将字体文件copy到linux服务器/usr/share/fonts/zh_CN目录下。

第一步:从windows或者mac上获取字体文件,mac上的字体文件地址为:/Library/Fonts,windows字体地址为:c盘下的Windows/Fonts。将Fonts目录打包上传到linux服务器/usr/share/fonts/zh_CN目录下,然后解压。

第二步:设置权限

chmod -R 755 /usr/share/fonts/zh_CN

第三步:生成fonts.scale

yum -y install ttmkfdir
ttmkfdir -e /usr/share/X11/fonts/encodings/encodings.dir

第四步:修改字体配置文件

vim /etc/fonts/fonts.conf
在<dir>....</dir>列表中添加字体
如:<dir>/usr/share/fonts/zh_CN/Fonts</dir>

第五步:刷新字体缓存

fc-cache

命令行运行headless chrome需要使用–disable-gpu参数吗?

目前--disable-gpu 标志在处理一些bug时是需要的,在未来版本的 Chrome 中就不需要了。

系统仍然需要安装Xvfb吗?

不需要,Headless Chrome 不使用窗口,所以不需要像 Xvfb 这样的显示服务器。
你问什么是 Xvfb?
Xvfb 是一个用于类 Unix 系统的运行于内存之内的显示服务器,可以让你运行图形应用程序(如 Chrome),而无需附加的物理显示器。许多人使用 Xvfb 运行早期版本的 Chrome 进行 “headless” 测试。

如何创建一个运行 Headless Chrome 的 Docker 容器?

查看 lighthouse-ci。它有一个使用 Ubuntu 作为基础镜像的 Dockerfile 示例,并且在 App Engine Flexible 容器中安装和运行了 Lighthouse。

headless chrome和 PhantomJS 有什么关系?

Headless Chrome 和 PhantomJS 是类似的工具。它们都可以用来在无需显示的环境中进行自动化测试。两者的主要不同在于 Phantom 使用了一个较老版本的 WebKit 作为它的渲染引擎,而 Headless Chrome 使用了最新版本的 Blink。

下篇将介绍分布式漏扫爬虫框架的设计与实现,以及写爬虫过程中需要注意的点

https://zhuanlan.zhihu.com/p/29207391
https://developers.google.com/web/updates/2017/04/headless-chrome
https://juejin.im/entry/58fd5e645c497d005803b6a4
http://csbun.github.io/blog/2017/09/puppeteer/


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK