Giter VIP home page Giter VIP logo

blog-html-to-pdf's Introduction

简介

事情是这样的,我的一位朋友是 Brendan Gregg 的粉丝(啊,我也是), 想把他的 blog 保存成 PDF,放到 kindle 上随时研读, 群里讨论起来,就聊起来有没有一些好的办法能够把 130 文章由 HTML 转成 PDF。

简单想了下,要解决这个问题,有三个步骤:

  • 拿到 130 篇 blog 文章的 url
  • 将每篇文章由 HTML 转换成 PDF
  • 最后再将转换后的 PDF 合成一个大的 PDF 文件

重点在于前两步。

拿到所有 blog 文章的 url

第一步,拿到一个网站或者多个网站的所有 url,本质上是一个爬虫问题。 wget 是一个非常好用的下载工具,除了下载单个文件, 还具有断点续传的功能;除此之外,wget 还可以下载一整个网站并将网站的链接转换成本地链接。

我们用下面的命令拿到 brendan gregg 网站的所有链接:

wget --spider -r http://www.brendangregg.com/blog/ 2>&1 | grep '^--' | awk '{ print $3 }' | grep -v '\.\(css\|js\|png\|gif\|jpg\|JPG\)$' > /tmp/urls.txt

我们发现 brendan gregg 网站的 blog 的 url 非常有规律:

http://www.brendangregg.com/blog/2008-12-02/a-quarter-million-nfs-iops.html
http://www.brendangregg.com/blog/2008-12-15/up-to-2gbs-nfs.html
http://www.brendangregg.com/blog/2008-12-15/up-to-2gbs-nfs.html
http://www.brendangregg.com/blog/2009-01-09/1gbs-nfs-from-disk.html
http://www.brendangregg.com/blog/2009-01-09/1gbs-nfs-from-disk.html

于是我们用如下的命令过滤出所有 blog 文章的 url:

cat /tmp/urls.txt | grep 'blog/2' | grep '.html$' |  sort | uniq  > blog.txt

到此,第一步完成。

将文章由 HTML 转换成 PDF

接下来,我们要将 130 篇文章全部由 HTML 转换成 PDF。

显然,手工做是不可以滴。批量转换必须用到 headless browser

前几年 headless browser 的事实标准是 PhantomJS,不过后来 Chrome 团队放了个大招 Puppeteer,基本上 算宣告了 PhantomJS 寿终正寝。

我们可以用下面的代码来截图:

const puppeteer = require('puppeteer');

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

  await browser.close();
})();

略微 封装 一下,我们可以将 130 篇 blog 文章全部转换成 PDF。

需求注意的问题:

  • JS 中写异步代码并不是特别舒服,如有可能,尽可能用 async/await 的方式,写起来舒服很多;
  • Puppeteer 本质上是一个 chrome,页面多的话相当耗资源,因为截图的时候需要控制下频率, 每次截图之后关闭 page,并 sleep(10000)。我第一版的代码没有注意到这个问题并同时 disable 了 headerless 选项 (const browser = await puppeteer.launch({headless: false}), 直接导致电脑内存耗光,现在了数十个 chromium 共存的感人画面:

完整的截图代码在 这里

运行:

yarn
mkdir output
node index.js

合并 pdf

大概花十几分钟的样子,我们可以拿到约 130 篇文章的 PDF,接下来我们将 130 篇 PDF 合并成一个大 的 PDF 文件,这样可以方便在移动设备上管理和阅读。

合并 PDF 的工具相当多,专业的如 Adobe Acrobat,命令行的工具有 PDFtk

Mac 上可以用 ghostscript

brew install ghostscript

合并 PDF 可以用类似下面的命令:

gs -q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -sOutputFile=merged.pdf pdf1.pdf pdf2.pdf

我们用 ls -t 命令列出所有的 PDF 文件,并按照文件的 modifed time 进行排序(man ls 命令 查看 -t 参数的含义。

如此,我们得到下面的命令:

gs -q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -sOutputFile=merged.pdf `ls -t`

大约一两分钟的样子,130 个 PDF 合并成一个 640+ 页的 PDF。我提供两种版本下载:

思考

一呢,其实如果放到 kindle 这种小尺寸的设备上阅读的话,puppeteer 的截图参数还可以再改一下。 我在程序里的设定是按照 A4 尺寸转换成 PDF,如果放到 kindle 上阅读,用 A5 的尺寸转 PDF 也许 阅读效果会更好一点,这个时候,web 这种流式排版—— 流式排版这个名词是我自创的,嗯 ——在适配不同尺寸设备方面就显示出了巨大的优势。

二,如果做一个类似的 web 服务,会有人愿意买单么?

三,工具的强是无敌的……

blog-html-to-pdf's People

Contributors

xiaohanyu avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.