Puppeteer:使用总结(一) 如何使用Puppeteeer导出网页中选中的内容
背景
前端时间公司出台新规定,上班时间禁止浏览与“工作无关”的网页。当然这个有没有关不是自己定的而是公司定的,其中就包含各种技术论坛。
什么?你说你可以偷偷上让老板发现不了?只能说你too young too simple。
最保险的办法不是偷偷上不让老板发现,也不是通过各种牛逼手段绕过监控。那是啥呢?就是真的不上。作为一个高龄程序员,知道有些红线是不能碰的。别问我为啥知道~~
但是在公司查看各种离线文档,PDF啥都是没有问题的,毕竟为了工作我也得时刻保持学习。要不然不等后浪,自己就先晒死在沙滩上了。
既然PDF离线文档都没有问题,哈哈哈:有了(程序员的快乐就这么简单)。
目录
背景
Puppeteer简介
手动生成PDF
生成整个网页
仅生成选中部分
初步使用Puppeteer
基本思路
调用PDF的API
把选中的内容生成PDF
总结
Puppeteer简介
前段时间正好学了一下Puppeteer 知道他可以把网页导出成PDF,准确的说是Chrome可以。OK, 那么什么是Puppeteer ?
Puppeteer 是一个 Node 库,它提供了一个高级 API 来通过 DevTools 协议控制 Chromium 或 Chrome。Puppeteer 默认以 headless 模式运行,但是可以通过修改配置文件运行“有头”模式。
没错,Puppeteer就是一个Node库,包装了对Chrome的各种控制。这里就不深入展开讨论。想继续深入学习Puppeteer的同学传送门在这里>puppeteer<.
手动生成PDF
生成整个网页
打开任何一篇CSDN文章,比如:PowerShell:如何一行代码(脚本)刷抖音快手视频?老司机教你如何薅羊毛(二)【多线程版】_火星蛙的博客-CSDN博客
然后点击 右键,选择打印
然后会弹出打印预览页面,但是出来的预览页面让我很不满意,左边的广告栏把正文的内容都挤跑了。这样生成的PDF拿到公司也没法看啊。
效果让人很不满意,而且我想要的内容只是,文章的正文。
仅生成选中部分
既然整个网页导出成PDF有问题,那么部分网页呢?或者说只是选中的部分呢?
再次调出打印预览页面,在“更多设置”里面选中“仅限选定内容”。嗯是我想要的效果,小姐姐也正确的显示出来了。
那就是用Poputeer也要达到类似的效果。
初步使用Puppeteer
基本思路
既然Puppeteer只是Chrome 的一个包装库,那么在Chrome上手动操作能做的事情,大概Puppeteer也能做吧。我主观的认为。而且我记得Puppeteer是有生成PDF这个功能的。
既然这样再确定一下Puppeteer转PDF的基本思路:
1. 打开一个网页比如:PowerShell:如何一行代码(脚本)刷抖音快手视频?老司机教你如何薅羊毛(二)【多线程版】_火星蛙的博客-CSDN博客
2. 选中要生成PDF的内容
3. 调用生成PDF的API导出PDF
看起来没什么难度。
调用PDF的API
Puppeteer官网上给出了生成PDF的示例代码:
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch(); // 打开浏览器
const page = await browser.newPage(); //创建一个新的tab
await page.goto('https://news.ycombinator.com', {waitUntil: 'networkidle2'}); //在这个新的tab里打开想要的网页
await page.pdf({path: 'hn.pdf', format: 'A4'}); //生成PDF,两个参数: path:PDF文件名,可以是全路径名也可以是单单文件名(输出到当前工作目录);format:页面输出格式,这里用的是A4格式await browser.close(); //关闭浏览器
})();
OK,看起来也很容易上手。那么针对我要导出的CSDN文章替换掉相应的参数,来试试。page.pdf 的更多参数请参考这里。
首先新建一个目录csdntopdf,然后在目录下面运行:
npm init #各种回车npm install puppeteer -save
去csdntopdf目录下面创建csdntopdf.js文件,放入下面的内容
const puppeteer = require('puppeteer');(async () => { try { const browser = await puppeteer.launch(); const page = await browser.newPage(); await page.goto('https://blog.csdn.net/gjmjack/article/details/120338321', { waitUntil: 'networkidle2' }); await page.pdf({ path: '如何一行代码(脚本)刷抖音快手视频?老司机教你如何薅羊毛(二)【多线程版】.pdf', format: 'A4' }); await browser.close(); } catch (error) { }})();
保存,然后代码结构看起像下面的:
运行:
Node csdntopdf.js
不出所料,果然生成了PDF文件,如下所示。但是,结果像翔一样,不是很满意啊,这玩意让我怎么欣赏?
把选中的内容生成PDF
按照我们的思路应该把选中的内容生成PDF才对,因为那些无关紧要的广告我是不想看到。而且那东西会导致生成的PDF变形没法看。带到公司看也不合适,一个文档里面全是广告,如何跟领导解释?
但是我还是太天真了,找遍了puppeteer的官方文档都没要找到一个API可以选定元素然后再导出成PDF,也许它藏在某个卡卡里头我没有找到。但是这不重要。问题是现在貌似有点玩不下去了啊T_T。
正当我一筹莫展时,我看到了它:
page.addStyleTag(options)v0.9.0
options
url
link标签的href属性值path
样式文件的路径. 如果path
是相对路径,那么相对 当前路径解析。content
css代码(即)- 返回: <Promise> Promise对象,即注入完成的tag标签。当style的onload触发或者代码被注入到frame。
添加一个指定link(url)的
标签。 或者添加一个指定代码(content)的
标签。
page.mainFrame().addStyleTag(options) 的简写。
哈哈,这是啥?这是可以往页面里面注入CSS啊,这不就相当于F12调试里面干的事吗?我一拍大腿(卧艹拍疼了):老子不能选,还不能隐藏吗?把没用的东西都隐藏,剩下的不就是我想打印的吗?
我怎么这么聪明这么牛逼?看来发际线不是白高的。
先来尝试一下,嗯,广告栏没有了,帅!
继续
这下把该隐藏的都隐藏了,版权信息还是保留,毕竟不是自己的东西。但是位置还是不是太理想,OK调整一下:
这下不错满意了,CSS代码如下:
.recommend-box.insert-baidu-box,div.comment-box,.second-recommend-box.recommend-box,.first-recommend-box.recommend-box,div.blog-footer-bottom,#toolBarBox,div.csdn-side-toolbar,aside.blog_container_aside,#csdn-toolbar{ display:none !important;}.nodata .container main {width: 90% !important;}.nodata .container { width: 100% !important; display:flex; justify-content:center; padding:0;}
把上面的CSS注入到页面上,再生成PDF试一下。 Perfect!
感觉非常完美,献上代码:
const puppeteer = require('puppeteer');(async () => { try { const browser = await puppeteer.launch(); const page = await browser.newPage(); await page.goto('https://blog.csdn.net/gjmjack/article/details/120338321', { waitUntil: 'networkidle2' }); //注入CSS代码 await page.addStyleTag( { content: ` .recommend-box.insert-baidu-box, div.comment-box, .second-recommend-box.recommend-box, .first-recommend-box.recommend-box, div.blog-footer-bottom, #toolBarBox, div.csdn-side-toolbar, aside.blog_container_aside, #csdn-toolbar{ display:none !important; } .nodata .container main {width: 90% !important;} .nodata .container { width: 100% !important; display:flex; justify-content:center; padding:0; } ` }) await page.pdf({ path: '如何一行代码(脚本)刷抖音快手视频?老司机教你如何薅羊毛(二)【多线程版】.pdf', format: 'A4' }); await browser.close(); } catch (error) { }})();
运行环境:
node -vv14.16.1npm -v6.14.12
完整代码示例请点击下面链接下载:
https://download.csdn.net/download/gjmjack/23639553
到上面的步骤似乎我们所有的工作已经完成了,我们已经完全按照预想的思路完成了所有步骤并且实现了代码导出网页成PDF。但是,这真的是我想要的吗?
未完待续。。。
总结
- Puppeteer可以像手动使用Chrome一样用代码操作Chrome并且不需要界面(Chrome headless模式)
- 使用Puppeteer的page.pdf可以把网页导出PDF
- 使用page.addStyleTag可以往网页上注入CSS在生成PDF的时候可以把网页上不需要的内容隐藏掉