学习目标:
以PDF形式保存网页
学习内容:
- nodejs web 转化pdf 库
- nodejs 循环
- nodejs 多线程控制
- nodejs 文件与字符串处理
背景
最近突发奇想,想把网站转化为pdf资料,便于携带,查看等。以下记录下学习过程,那么让我们开始把。
nodejs web 转化pdf 库
首先,经过调研。发现了这样的一个nodejs可用的web转换pdf的库, puppeteer, 中文文档
不多说, npm init
, npm install puppeteer
然后参考README
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('https://exsample.com', {waitUntil: 'networkidle2'});
await page.pdf({path: 'hn.pdf', format: 'A4'});
await browser.close();
})();
nodejs 循环
接下来第二步,我有很多网页要下载怎么办?循环。
const puppeteer = require('puppeteer');
async function downloadedPage(url){
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto(url, {waitUntil: 'networkidle2'});
await page.pdf({path: url+'.pdf', format: 'A4'});
await browser.close();
});
urls = ['example.com','another.com'];
function main() {
urls.forEach(async function(url) {
console.log(url);
await downloadedPage(url);
return;
});
}
nodejs 多线程控制
考虑效率,因为我们考虑到很多网页一个一个去下载的效率是线性的。好在我们的downloadedPage
函数本身就是异步的。但是因此带来的问题是我们内存有限,一旦urls
这个数组过大。。。就内存溢出了。
因此:采用count down lock的思路来控制并发。并发下载数目为10.
async.mapLimit(urls, 10, async function(url) {
console.log('todo downloads:',total);
await downloadedPage(url);
total--;
return;
}, function (err, result) {
//所有连接抓取成功,返回回调结果列表
//console.log(result);
});
nodejs 文件与字符串处理
继续改进,解决问题,使得项目体验符合预期。
我们还有什么预期呢?
- 我可不想一直开着电脑。
因此,我们要对于程序进行检测。在downloadedPage
中插入检测片段如下:
filename = repalceAll('\n','',filename);
if(fs.existsSync(filename+'.pdf')) {
console.log('skip');
return;
}
这样我可以开电脑下载,然后关机,第二天重新下载的时候,看到已经存在的网页就会跳过了。
- 我可不想维护一个超大的数组。
读文件, 维护一个文件列表,然后把url按照列别放到对应的列表里,之后进行下载即可。
var paths = ['file1','file2'];
for (var i = 0; i < paths.length; i++) {
var data = fs.readFileSync(paths[i]);
//console.log(data.toString());
//a.push.apply(a,b);
urls.push.apply(urls,data.toString().trim().split(","));
}