某旅行社网站建设规划书,深圳百姓网,上海十大知名装修公司,三亚网站制文章目录 上一篇效果演示Puppeteer 修改浏览器的默认下载位置控制并发数错误重试并发控制 错误重试源码 上一篇
Puppeteer 使用实战#xff1a;如何将自己的 CSDN 专栏文章导出并用于 Hexo 博客#xff08;一#xff09;
效果演示
上一篇实现了一些基本功能#xff0c;… 文章目录 上一篇效果演示Puppeteer 修改浏览器的默认下载位置控制并发数错误重试并发控制 错误重试源码 上一篇
Puppeteer 使用实战如何将自己的 CSDN 专栏文章导出并用于 Hexo 博客一
效果演示
上一篇实现了一些基本功能但是还有些问题
有些时候页面会卡死或者说找不到导出的元素导致这篇文章下载不了不能控制标签页的打开数量不够灵活只能一个标签页、一个标签页的工作效率低下下载文件的默认位置没有修改
根据上面的问题这次添加了并发控制以及错误重试效果如下图 Puppeteer 修改浏览器的默认下载位置
查了官网好久的相关配置没找到然后谷歌终于在这个网站上找到了答案 我的代码修改在这里了注意声明的位置一定要提前 import path from path;
const __dirname path.resolve(path.dirname());
const myDownloadPath ${__dirname}\\my-post;const page await browser.newPage();const client await page.createCDPSession();await client.send(Page.setDownloadBehavior, {behavior: allow,downloadPath: myDownloadPath,});这里提一嘴我原先是把代码放到下图这个位置每次新建页面下重新设置发现总是有些小 bug
有的时候会下载到浏览器的默认目录也就是代码根本没生效多线程的时候会部分放到指定目录部分放到默认目录比方说双并发的时候具体问题看我下面的图 给我的感觉它算是一个全局的修改所以只需要提前声明一次即可不用每一次新建 newPage 就设置一次 控制并发数 这个可以参考一下这个叫 async-pool 的库的源码
我在这儿写了一个小案例可以试试
// https://github.com/rxaviers/async-pool/blob/1.x/lib/es7.js
async function asyncPool(poolLimit, iterable, iteratorFn) {const ret [];const executing new Set();for (const item of iterable) {const p Promise.resolve().then(() iteratorFn(item));ret.push(p);executing.add(p);const clean () executing.delete(p);p.then(clean).catch(clean);if (executing.size poolLimit) {await Promise.race(executing);}}return Promise.all(ret);
}const timeout (i) {console.log(开始 i);return new Promise((resolve) setTimeout(() {resolve(i);console.log(结束 i);}, 1000 Math.random() * 1000));
};let urls Array(10).fill(0).map((v, i) i);
console.log(urls);(async () {const res await asyncPool(2, urls, timeout);console.log(res);
})();
错误重试 也是用了一个 demo 逻辑
const retry (fn, times) {return new Promise((res, rej) {const attempt () {fn().then(res).catch((error) {times-- 0 ? attempt() : rej(机会用光了);});};attempt();});};let getNum function () {console.log(函数执行一次);return new Promise((res, rej) {let num Math.random() * 10;num 2 ? res(数字小于2) : rej(数字大于2);});};retry(getNum, 3).then((mes) {console.log(mes);}).catch((err) {console.log(err);});并发控制 错误重试
结合之前的两个 demo我们修改一下自己的逻辑
// tools.js
function retry(fn, times, item) {const allTime times;const articleId item.split(articleId)[1] || ;return new Promise((res, rej) {const attempt () {const currTime allTime - times 1;fn().then(() {console.log(Retry Success: 第 ${currTime} 次重试 ${articleId} 成功!);res(item);}).catch((error) {console.log(Warning: 第 ${currTime} 次重试 ${articleId} );if (times-- 0) {attempt();} else {console.log(Error: 已经重试 ${item} 文章 ${currTime} 次机会已用光);rej();}});};attempt();});
}// https://github.com/rxaviers/async-pool/blob/1.x/lib/es7.js
export async function asyncPool(poolLimit, iterable, iteratorFn) {const ret [];const executing new Set();for (let i 0, len iterable.length; i len; i) {const item iterable[i];const articleId item.split(articleId)[1] || ;const p Promise.resolve().then(() iteratorFn(item)).catch(async (err) {console.log(${articleId} 解析失败即将重试);// 这里的 retry 也添加上 awaitawait retry(() iteratorFn(item), 3, item).catch(() {});});ret.push(p);executing.add(p);const clean () executing.delete(p);p.then(clean).catch(clean);if (executing.size poolLimit) {await Promise.race(executing);}}return Promise.all(ret);
}然后调用一下
await asyncPool(3, baseWriteURLArray, handleURL);源码
想要源码可以查看此仓库如果有用记得 star 一下哦 https://github.com/Lovely-Ruby/CSDNBlogsExport