V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
爱意满满的作品展示区。
chengkai
V2EX  ›  分享创造

几行代码搭建一个网页转 PDF 的服务

  •  
  •   chengkai ·
    examplecode · 2019-11-12 15:50:59 +08:00 · 5032 次点击
    这是一个创建于 1599 天前的主题,其中的信息可能已经有所发展或是发生改变。

    搭建一个网页转 pdf 的服务实际上只需几行代码,转给有需要的同学,正文如下。

    原文链接:http://doc.xbext.com/devopt/using-puppeter-convert-webpage-to-pdf-and-fullpage-screenshot/

    最近需要为x 浏览器 提供一个网页转 PDF 的服务,鉴于 X 浏览器定位是一个简洁轻便的手机浏览器产品,所以打算在服务端实现这一功能,同时为了更好的为 X 浏览器客户端服务,所以准备自己尝试搭建这么一套服务。去年的时候曾经看到过关于 Puppeteer 的相关文章,知道通过这个产品可以实现网页转 pdf 以及生成整页截图。这篇文章用来记录如何使用这组件来搭建一个网页转 pdf 的服务。

    什么是 Puppeteer

    Puppeteer 是由 GoogleChrome 团队维护的一套基于 NodeJs 的 API 用于操控HeadLess Chrome 。headless chrome 其实是一个没有 UI 界面的 Chrome 浏览器,除此之外几乎和真正的 Chrome 没有差别。这时候你可能会奇怪没有界面的 Chrome 怎么用啊?是的对于普通用户来讲 Headless Chrome 确实无法使用,但是对于一些自动化测试的场景使用 Headless Chrome 就太方便了。我们只要通过命令行就可以对 Chrome 进行操控完成普通浏览器所用使用场景,打开页面,填写表单,点击按钮,甚至模拟鼠标及触屏,都完全不在话下。

    Puppeteer 提供了一套完备的API使我们我们可以方便的操控 Chrome,我们通过 UI 界面可以完成的操作都可以通过 Puppeteer 来实现。

    下面介绍如何安装 Puppeteer 以及使用 Puppeteer 提供整页截图和生成 pdf 文件。

    在 Linux 环境下部署 Puppeteer

    为了安装部署方便,我们选择 ubutun 18.04 作为后台服务,在这之前我需要先安装 NodeJs 运行环境,Puppeteer 的一些最新特性需要在 Node v7.6.0 或更高版本中才被支持。所以我们选择安装 NodeJs 的 8.x 版本。

    curl -sL https://deb.nodesource.com/setup_8.x | sudo -E bash -
    sudo apt-get install -y nodejs
    

    安装 Puppeteer

    mkdir puppeteer-demo
    cd puppeteer-demo
    npm i  puppeteer
    

    安装的过程中会自动下载 HeadlessChrom, 完整安装后我们可以通过下面的脚本测试 puppeteer 是否可以和 HeadlessChrom 一起正常工作。

    //version.js
    const puppeteer = require('puppeteer');
    (async() => {
      const browser = await puppeteer.launch();
      console.log(await browser.version());
      await browser.close();
    })();
    
    

    运行脚本

    node verison.js
    

    工作正常的话会显示 headless chromed 的版本号

    HeadlessChrome/79.0.3945.0
    

    转换网页到 pdf 格式

    下面的代码展示了使用 Puppeteer 如何把网页转换为 pdf 格式.

    const puppeteer = require('puppeteer');
    
    (async() => {
    const browser = await puppeteer.launch();
    const page = await browser.newPage();
    
    await page.goto('https://www.xbext.com', {waitUntil: 'networkidle2'});
    await page.pdf({path: 'page.pdf', format: 'A4'});
    
    await browser.close();
    })();
    
    

    生成整页网页截图

    下面代码展示了如何模仿手机作为请求,并且生成整个网页的截图

    const puppeteer = require('puppeteer');
    
    (async () => {
      const browser = await puppeteer.launch();
      let page = await browser.newPage();
      const userAgent = "Mozilla/5.0 (Linux; Android 8.1.0; MI 8 Build/OPM1.171019.011; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/62.0.3202.84 Mobile Safari/537.36";
      page.setUserAgent(userAgent);
      
      //await page.setViewport({ width: 1920, height: 1080 });
    
      await page.setViewport({ width: 480, height: 800,isMobile: true}); 
    
      await page.goto('https://www.xbext.com',{waitUntil: 'networkidle2'});
    
      await page.screenshot({path: 'myscreeshot.png',fullPage: true});
      //如图片过大可以通过生成.jpg 文件并且控制图标质量
      //await page.screenshot({path: 'myscreeshot.jpg',fullPage: true,quality: 80});
      await browser.close();
    })();
    
    

    相关问题

    运行 puppeteer 脚本时候无法启动 Chrome ,提示如下错误

    chrome-linux/chrome: error while loading shared libraries: libasound.so.2
    

    安装缺失的库即可

    sudo apt-get install libasound2
    

    无法渲染中文

    生成 pdf 或截图的时候,中文字符显示为一个个小方块,是因为缺失中文字体文件,导致 chromium 无法正常渲染,使用下面的命令安装即可.

    sudo apt-get install language-pack-zh*
    sudo apt-get install chinese*
    

    参考资料

    https://developers.google.com/web/updates/2017/04/headless-chrome

    6 条回复    2019-11-15 15:38:48 +08:00
    aisusu
        1
    aisusu  
       2019-11-12 16:10:35 +08:00
    Puppeteer 的另一个应用场景是爬虫,用于搞定 JS 渲染页面的内容抓取。
    djyde
        2
    djyde  
       2019-11-13 16:14:08 +08:00
    liuzhaowei55
        3
    liuzhaowei55  
       2019-11-14 11:39:48 +08:00
    推荐一个猜测是 wikipedia 现在在用的 PDF 渲染库:
    https://github.com/msokk/electron-render-service
    不过这个库现在 GitHub 标记 DEPRECATED,推荐了另外一个库:
    https://github.com/alvarcarto/url-to-pdf-api
    chengkai
        4
    chengkai  
    OP
       2019-11-14 15:58:57 +08:00
    @djyde 这倒是一个不错的商业模式,可以拿来收钱了。不过这个东西容易被滥用,尤其是在国内搞一些撸羊毛的活动。
    chengkai
        5
    chengkai  
    OP
       2019-11-14 16:03:51 +08:00
    @liuzhaowei55 其底层原理都是基于 HeadlessChrome , 使用 Puppeteer 更加简单。
    xgfan
        6
    xgfan  
       2019-11-15 15:38:48 +08:00
    这个生成的 PDF 是可编辑的吗?(可以选择里面的文字,图片,🔗可点击)
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   2691 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 15:09 · PVG 23:09 · LAX 08:09 · JFK 11:09
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.