简介
Chrome 59版本之后开始搭载Headless Chrome,Headless Chrome 是 Chrome 浏览器的无界面形态,在不使用UI界面的情况下,可以访问并运行网页。通过Headless,就可以很方便的在服务器上测试网页和爬虫了~
Puppeteer 是一个 Node 库,它提供了一个高级 API 来通过 DevTools 协议控制 Chromium 或 Chrome。
Puppeteer API 是分层次的,反映了浏览器结构。来源
Puppeteer使用 DevTools 协议 与浏览器进行通信。Browser实例可以拥有浏览器上下文。BrowserContext实例定义了一个浏览会话并可拥有多个页面。Page至少有一个框架:主框架。 可能还有其他框架由 iframe 或 框架标签 创建。frame至少有一个执行上下文 - 默认的执行上下文 - 框架的 JavaScript 被执行。 一个框架可能有额外的与 扩展关联的执行上下文。Worker具有单一执行上下文,并且便于与 WebWorkers 进行交互。
安装和使用
安装puppeteer模块:
npm install puppeteer --save
在安装puppeteer模块的时候,会自动安装Chromium,但是还不能直接使用,还需要安装一些依赖项:
#依赖库yum install pango.x86_64 libXcomposite.x86_64 libXcursor.x86_64 libXdamage.x86_64 libXext.x86_64 libXi.x86_64 libXtst.x86_64 cups-libs.x86_64 libXScrnSaver.x86_64 libXrandr.x86_64 GConf2.x86_64 alsa-lib.x86_64 atk.x86_64 gtk3.x86_64 -y#字体yum install ipa-gothic-fonts xorg-x11-fonts-100dpi xorg-x11-fonts-75dpi xorg-x11-utils xorg-x11-fonts-cyrillic xorg-x11-fonts-Type1 xorg-x11-fonts-misc -y
到这里,我们来运行官方给的demo:
const puppeteer = require('puppeteer');(async () => {const browser = await puppeteer.launch();const page = await browser.newPage();await page.goto('https://example.com');await page.screenshot({path: 'example.png'});await browser.close();})();
发现还是不能正常运行,原因是Chrome为了保护主机环境不受不受信任的Web内容的影响,使用了多层沙盒。为了使其正常工作,应该首先在主机配置好沙盒。如果没有好的沙盒供Chrome使用,它将崩溃,并出现错误:没有可用的沙盒!
启动的时候可以通过参数来让Chrome不使用沙盒:
const browser = await puppeteer.launch({args: ['--no-sandbox', '--disable-setuid-sandbox']});
我们再运行程序,发现可以正常运行了。我们修改一下代码,来解析一个出一个视频播放页的播放地址:
const puppeteer = require('puppeteer');(async function() {const browser = await puppeteer.launch({args: ['--no-sandbox', '--disable-setuid-sandbox']});const page = await browser.newPage();// 设置浏览器 Viewport 和 UAawait page.setViewport({width: 375,height: 667});await page.setUserAgent('Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1');// 视频播放页地址let page_url = 'http://hztv.hangzhou.com.cn/video.php?video_id=40202';await page.goto(page_url).catch((err) => {console.log('get page err', page_url, err);});// 延迟1秒~让页面的js完全执行await dalay(1000);const data = await page.evaluate(() => {// 注意,这里写的js代码运行在浏览器端let videoUrl = '';let video = document.getElementsByTagName('video')[0];if (video && video.src) {videoUrl = video.src;} else {let source = document.getElementsByTagName('source')[0];videoUrl = source && source.src;}return {title: document.title,videoUrl: videoUrl,};}).catch((err) => {console.log('catch err', err);});// 输出信息console.log(data);// 关闭页面和浏览器await page.close();await browser.close();})();async function dalay(time) {return new Promise((resolve, reject) => {setTimeout(() => {resolve();}, time);});}
运行之后解析成功,输出如下:
{ title: '杭网宽频-车祸现场停车看热闹 司机被罚款400元 记18分',videoUrl: 'http://hzwsp.hangzhou.com.cn/hztv/transcode/2018/11/27/5bfc99f5b99f3_fluency.mp4' }
API:https://github.com/GoogleChrome/puppeteer/blob/v1.15.0/docs/api.md
中文API:https://zhaoqize.github.io/puppeteer-api-zh_CN/
