

GitHub - xiaohanyu/blog-html-to-pdf: A sample program to convert blog website to...
source link: https://github.com/xiaohanyu/blog-html-to-pdf
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

README.md
简介
事情是这样的,我的一位朋友是 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 寿终正寝。
我们可以用下面的代码将 HTML 网页转存成 PDF:
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,页面多的话相当耗资源,因此 HTML 转存 PDF 的时候需要控制下频率,每次截图之后关闭 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。我提供两种版本下载:
思考
一呢,其实如果将 PDF 放到 kindle 这种小尺寸的设备上阅读的话,puppeteer 的截图参数还可以再改一下。我在程序里的设定是按照 A4 尺寸转换成 PDF,如果放到 kindle 上阅读,用 A5 的尺寸转 PDF 也许阅读效果会更好一点,这个时候,web 这种流式排版——流式排版这个名词是我自创的,嗯——在适配不同尺寸设备方面就显示出了巨大的优势。
二,如果做一个类似的 web 服务,会有人愿意买单么?
三,工具的强是无敌的……
Recommend
-
10
Can I somehow get my program to convert characters to integers? advertisements I have been running this and typing "12+" as the e...
-
7
Build your own RPM package with a sample Go program Skip to main content A deployment usually involve...
-
7
Sample GoCD Virtualbox based environment Ken Mugrage If you're interested in checking out GoCD but don't want to spend the time automating your own system, this might be a great option for you. We'...
-
10
Java Program to Convert String to an IntegerJava Program to Convert String to an IntegerToday we are going to learn the
-
4
C++ Program to Convert Decimal Number to BinaryC++ Program to Convert Decimal Number to Binary180 Views26/05/2022In this video we will see...
-
6
NASA, Partner Establish New Research Group for Mars Sample Return Program Sixteen scientists from the U.S., Europe, Canada, and Japan have been chosen to help future samples fro...
-
9
C++ Program to Convert Octal Number to Decimal and vice-versaC++ Program to Convert Octal Number to Decimal and vice-versaHello friends. Welcome to Geeks. Forgive third, today's
-
6
Python Program to Convert String to an IntegerPython Program to Convert String to an Integer20 Views17/06/2022In this video, we will learn...
-
11
C++ Program to Convert Lowercase to Uppercase & vice versaC++ Program to Convert Lowercase to Uppercase & vice versaHello everyone. Welcome back to Geeks. For geeks
-
7
C++ Program to Convert Decimal to HexadecimalC++ Program to Convert Decimal to HexadecimalHello friends. Welcome to the Geeks for Gibbs.
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK