学习
实践
活动
工具
TVP
写文章
专栏首页Serverless+在 SCF 中运行 Puppeteer
原创

在 SCF 中运行 Puppeteer

Puppeteer 是一个 Node.js 库, 提供了一组封装良好的接口, 使你可以通过 DevTools 协议控制 Chrome. 本文介绍如何在 SCF 中使用 Puppeteer.

一个截图的例子

我们使用官方仓库里的截图例子

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();
})();

将其改造一下, 使其可以在 SCF 上运行

// index.js
'use strict';

const puppeteer = require('puppeteer');
const fs = require('fs');

exports.main_handler = async (event, context, callback) => {
    const browser = await puppeteer.launch();
    const page = await browser.newPage();
    await page.goto('https://example.com');
    await page.screenshot({path: '/tmp/example.png'});
    await browser.close();

    let img = fs.readFileSync('/tmp/example.png');
    let data = {
        isBase64Encoded: true,
        statusCode: 200,
        headers: {'content-type': 'image/png'},
        body: img.toString('base64'),
    };
    return data;
};

为了可以看到截图的效果, 我们可以添加一个 API 网关触发器, 并将图片以 Base64 编码的格式返回.

至此, 我们期望这个函数可以在 SCF 上正确运行.

运行函数

在本地创建一个新项目, 把依赖装完后, 将代码打包上传至 COS, 创建一个新的 SCF 函数, 引用这个 COS 文件(由于打包生成的代码超过 50 MB, 你需要使用这种方式上传代码)

$ npm init
$ npm install puppeteer
$ tree -L 1 .
.
|-- index.js
|-- node_modules
|-- package.json
`-- package-lock.json

第一次运行

在控制台上点击测试, 你可能会看到如下错误:

Failed to launch chrome!
[0405/090101.405444:FATAL:zygote_host_impl_linux.cc(116)] No usable sandbox! Update your kernel or see https://chromium.googlesource.com/chromium/src/+/master/docs/linux_suid_sandbox_development.md for more information on developing with the SUID sandbox. If you want to live dangerously and need an immediate workaround, you can try using --no-sandbox.

我们按照提示来修复这个错误, 添加启动参数:

const browser = await puppeteer.launch({args: ['--no-sandbox']});

第二次运行

这一次, 你会遇到不一样的错误:

Error: Failed to launch chrome!
/var/user/node_modules/puppeteer/.local-chromium/linux-641577/chrome-linux/chrome: error while loading shared libraries: libXss.so.1: cannot open shared object file: No such file or directory

作为一个有经验的程序员, 你知道这是运行环境里缺少了必要的动态链接库, 你也发现机器上没有这个动态链接库, 搜索发现, 可以这样解决

$ yum install libXScrnSaver

安装完后, 你把 libXss.so.1/lib64 目录拷贝到项目到目录里, 并在代码中将项目的目录追加到 LD_LIBRARY_PATH 环境变量中.

// index.js
'use strict';

process.env['LD_LIBRARY_PATH'] += ';' + __dirname;

操作完后, 你想看看 Chrome 还依赖哪些动态链接库, 于是你执行了以下命令:

$ ldd node_modules/puppeteer/.local-chromium/linux-641577/chrome-linux/chrome

你会发现, Chrome 依赖多达 107 个动态链接库, 你可以选择把这些库都拷贝到当前目录, 这样就可以一劳永逸地解决依赖的问题.

你没有选择这样做, 因为这会使代码包变大许多, 你打包了代码, 再次运行.

第三次运行

问题不大, 你已经知道如何解决了

Error: Failed to launch chrome!
/var/user/node_modules/puppeteer/.local-chromium/linux-641577/chrome-linux/chrome: error while loading shared libraries: libatk-bridge-2.0.so.0: cannot open shared object file: No such file or directory

拷贝缺失的库到当前目录, 再次打包上传

第 X 次运行

你并没有崩溃 (:, 反复执行这个过程后, 你终于把缺失的动态库都补齐了

$ ls lib*
libatk-1.0.so.0         libatspi.so.0          libepoxy.so.0  libgtk-3.so.0           libwayland-egl.so.1  libXss.so.1
libatk-bridge-2.0.so.0  libcairo-gobject.so.2  libgdk-3.so.0  libwayland-cursor.so.0  libxkbcommon.so.0

函数终于可以正常运行了

{"isBase64Encoded":true,"statusCode":200,"headers":{"content-type":"image/png"},"body":"iVBORw0KGgoAAAANSUhEUgAAAyAAAAJYCAYAAACadoJwAAAAAXNSR0IArs4c6QAAIABJREFUeJzs3Xd8Tff/B/DXzZCIaOy9Y48vpdSmVFXtEETs0dqKIChVlEao1pbYKyFmrVBao5TG1qZ2iBBChiA7ef/+8HB+rqx7k3vPjdvX8/E4j0dy7uee8z7n8/mce95naqKiogVEREREREQqsDB1AERERERE9N/BBISIiIiIiFTDBISIiIiIiFTDBISIiIiIiFTDBISIiIiIiFTDBISIiIiIiFTDBISIiIiIiFTDBISIiIiIiFTDBISIiIiIiFTDBISIiIiIiFTDBISIiIiIiFTDBISIiIiIiFTDBISIiIiIiFTDBISIiIiIiFTDBISIiIiIiFTDBISIiIiIiFTDBISIiIiIiFTDBISIiIiIiFTDBISIiIiIiFTDBISIiIiIiFTDBISIiIiIiFTDBISIiIiIiFTDBISIiIiIiFTDBISIiIiIiFTDBISIiIiIiFTDBISIiIiIiFTDBISIiIiIiFTDBISIiIiIiFTDBI..."}

总结

本文介绍了如何解决在 SCF 中运行 Puppeteer 缺少动态链接库的问题. 缺失的库包括:

libatk-1.0.so.0         libatspi.so.0          libepoxy.so.0  libgtk-3.so.0           libwayland-egl.so.1  libXss.so.1
libatk-bridge-2.0.so.0  libcairo-gobject.so.2  libgdk-3.so.0  libwayland-cursor.so.0  libxkbcommon.so.0

完整的示例代码如下:

// index.js
'use strict';

process.env['LD_LIBRARY_PATH'] += ';' + __dirname;

const puppeteer = require('puppeteer');
const fs = require('fs');

exports.main_handler = async (event, context, callback) => {
    const browser = await puppeteer.launch({args: ['--no-sandbox']});
    const page = await browser.newPage();
    await page.goto('https://example.com');
    await page.screenshot({path: '/tmp/example.png'});
    await browser.close();

    let img = fs.readFileSync('/tmp/example.png');
    let data = {
        isBase64Encoded: true,
        statusCode: 200,
        headers: {'content-type': 'image/png'},
        body: img.toString('base64'),
    };
    return data;
};

你想通过 API 网关 看看效果, 没有如你所愿, 截图上的文本没有被正确显示, 但是聪明的你一定想到了, 这是字体的问题. 这个问题就留给读者自行解决啦!

原创声明,本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

登录 后参与评论
0 条评论

相关文章

  • travis-ci 中运行 puppeteer

    易墨
  • 搭建以 serverless 为后台服务的疫情热搜快应用

    今年疫情的影响越来越大,已经成为一个世界性的问题,疫情的发展时刻牵动每个人的心,正好也是因为疫情,今年让作为加班狗的我突然重温“放寒假”的感觉。宅在家里太久就想...

    dadong
  • 在kubernetes中运行openebs

    现在,OpenEBS是kubernetes下与容器原生和容器附加存储类型相关通用的领先开源项目之一。通过为每个工作负载指定专用的存储控制器,OpenEBS遵循容...

    有点技术
  • 在 Kubernetes 中运行 Kubernetes

    前面其实我们在 Windows 系统的 WSL2 下面使用 KinD 搭建了一套 Kubernetes 集群,KinD 是一个非常轻量级的 Kubernetes...

    我是阳明
  • 在windows中:双击运行Python

    一、安装Python解释器的windows环境,如果双击运行*.py的文件,会闪退。怎样避免闪退呢?

    py3study
  • 在docker中运行mysql实例

    Docker是一种新兴的虚拟化技术,能够一定程度上的代替传统虚拟机。下图是容器跟虚拟机的对比

    陈灬大灬海
  • 在docker中运行mysql实例

    Docker是一种新兴的虚拟化技术,能够一定程度上的代替传统虚拟机。下图是容器跟虚拟机的对比

    陈灬大灬海
  • 在IBM Cloud中运行Fabric

    上篇文章我们讲了怎么使用IBM blockchain platform extension在VS Code编辑器中创建本地运行的智能合约。

    程序那些事
  • 在Kubernetes集群中运行Nginx

    在完成前面kubernetes数据持久化的学习之后,本节我们开始尝试在k8s集群中部署nginx应用,对于nginx来说,需要持久化的数据主要有两块:

    星哥玩云
  • 在docker中运行Kali Linux

    当使用各种工具或创建隔离的环境时,Docker是虚拟化的绝佳替代品。Docker是轻量级的(在Linux上本机运行,没有虚拟机管理程序层),并且是不需要GUI的...

    点火三周
  • 在 .NET Core 中运行 JavaScript

    在 .NET Framework 时,我们可以通过V8.NET等组件来运行 JavaScript,不过目前我看了好几个开源组件包括V8.NET都还不支持 .NE...

    晓晨
  • [译] 在Kubernetes生产环境中运行Istio

    本文翻译自 https://www.tigera.io/blog/running-istio-on-kubernetes-in-production-part-...

    SammyLiu
  • 在Docker中运行PostgreSQL + pgAdmin 4

    默认username是postgres,password是上面设置的pg123456 注意,因为pgadmin运行在docker里,所以host不能写local...

    xhznl
  • 在jupyter notebook中运行R语言

    要想在jupyter notebook中运行R语言其实非常简单,按顺序安装下面扩展包即可:

    hankleo
  • 在VSCode中配置python运行环境

    使用Visual Studio Code来写Python,你将体验到丝滑的编程体验和无限扩展的可能。而且,如果你的项目是包含多种语言的,比如Web开发,你不必再...

    fem178
  • [linux]解决Calibre 在manjaro中运行不了

    最近升级了python3,然后发现Calibre 运行不了了,现象是点击桌面图标没有反应.使用命令行:calibre-debug -g 提示如下:

    djc8小码农
  • cmake:在Makefile中运行ant脚本

    版权声明:本文为博主原创文章,转载请注明源地址。 https://blog.csdn.net...

    用户1148648
  • 在 Podman 中运行 Linux 虚拟机

    Fedora CoreOS 是一个自动更新、基于最小rpm-ostree的操作系统,用于安全、大规模地运行容器化工作负载。

    KINGISS
  • 在Docker中运行kong和kong dashboard

    https://github.com/Kong/docker-kong/tree/d4cec3dc46c780a916a40963309554ca81da2b4...

    星哥玩云

扫码关注腾讯云开发者

领取腾讯云代金券