又双叒叕一堆 deno 的插件开源了,这次他们将目光转向了 puppeteer,deno-puppeteer、puppeteer_deno、deno-puppeteer-adapter…… 基本都是最近一个月诞生的,甚至还引发了“造轮子”的质疑。至于在 Deno中该如何使用 Puppeteer,如果您只是想简单运用,跟着Copy攻城狮的步伐就够了,如果您想深入了解,建议深入到源码中学习!
puppetter-deno
deno puppetter
puppeteer是一个Node库,它提供了高级API来通过DevTools协议控制Chrome或Chromium,puppeteer 默认以 headless 运行,但是可以通过修改配置文件完整(non-headless)运行。puppeteer常常被用来生成页面的屏幕截图和PDF、实现SSR、自动化测试等等,在业界也有不少企业级的运用,比如有赞商城前端团队使用puppeteer搭建统一海报渲染服务,TCB 的云函数也支持 puppeteer 依赖。于是也有开发者想在 deno 中使用puppeteer,就有了上图中的issue 。
deno-x-ranking puppetter
尽管有人排斥造轮子,但应该没人反对为了方便而使用轮子。抱着“这类轮子是不是很泛滥?”的疑问,我在 deno-x-ranking 上特意以 puppetter 进行了检索,这两个插件都是基于 puppetter 源码修改 -- “拥抱TS,拥抱 Deno”。既然轮子有了,赶紧安装试试!
Copy攻城狮的拿手本领当然是Copy啦,在尝试了截图中那个issue下的demo之后,发现还是在deno社区找到的puppeteer_deno好使。Just Do IT !
在Mac上,一小段代码就实现了截取掘金首屏:
// mod.ts
// 引入 puppeteer
import puppeteer from 'https://deno.land/x/pptr/mod.ts';
// 运行Chrome
const browser = await puppeteer.launch({
executablePath: '/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome',
});
// 打开掘金并截图、生成pdf
const page = await browser.newPage();
await page.goto('https://juejin.cn',{
waitUntil: 'networkidle2',
});
await page.screenshot({ path: 'juejin.png' });
await page.pdf({ path: 'juejin.pdf', format: 'a4' });
// 关闭
await browser.close();
执行deno run -A --unstable mod.ts
就能获取到如下结果,在当前目录生成juejin.png
和juejin.pdf
:
puppetter_deno
原本想从掘金的搜索入口入手,先从关键字搜索到用户列表,再从列表中的用户链接跳转到个人页,不过因为学艺不精被掘金的骨架屏难住了,另外我用的page.waitFor
也报错了,因此暂时从useid入手,获取指定useid的个人成就,代码惨不忍睹:
// mod.ts
// 引入 puppeteer
import puppeteer from 'https://deno.land/x/pptr/mod.ts';
// 运行Chrome
const browser = await puppeteer.launch({
executablePath: '/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome',
headless: true,
args: ['--no-sandbox', '--disable-setuid-sandbox'],
dumpio: false,
});
const page = await browser.newPage();
const uid = '1556564194374926'
// 跳转到指定id的个人页
await page.goto('https://juejin.cn/user/' + uid, {
waitUntil: 'networkidle2',
})
// 获取dom的信息
const staticInfo = await page.evaluate(() => {
const element:any = document.querySelector('.minor-area')
const elementLen:number = element.getElementsByClassName('stat-item').length
const obj:any = {}
for(let i:number = 0; i<elementLen;i++) {
obj[i] = element.getElementsByClassName('stat-item').item(i).querySelector('.content')
.innerHTML.replace(/<[^>]+>/g," ")
}
return {obj}
})
await browser.close()
console.dir(staticInfo)
以上代码返回掘金酱的个人成就:
{
obj: { "0": "掘金优秀作者", "1": "获得点赞 2,710 ", "2": "文章被阅读 386,134 ", "3": "掘力值 6,571 " }
}
总得来说在Deno上使用puppeteer能获取和Node同样优秀的体验,对Copy攻城狮来说,多一份代码多一种选择,大胆地尝试,总会有收获,哪怕只是微不足道的收获。每天进步一点点,一年更比一年好!