吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 2080|回复: 33
收起左侧

[学习记录] nodejs批量下载公众号文章为PDF

  [复制链接]
wusp1994 发表于 2023-8-3 17:40
本帖最后由 wusp1994 于 2023-9-7 17:45 编辑

2023-09-07更新

界面预览

1694079672357.jpg

1.0版本链接

链接:https://pan.baidu.com/s/1GbvnTYBIpTiOIccOOVs6YQ?pwd=52pj
提取码:52pj
--来自百度网盘超级会员V6的分享

2023-08-24更新

今天是日本排放核废水的日子,狗日小日本。
=============更新内容==================

  • 解决多图|纯图文章的问题。

  • 解决多篇文章,没有回到顶部,导致图片保存不全的问题。

  • 更新了,data 数据

    其他方式缺点

  • CTRL+P 一个一个太麻烦

  • 转换的PDF排版有问题

  • 转换的PDF内容缺失

  • 需要配置环境变量

功能点

  • 单个URL合成PDF( 完美排版 )
  • 多个URL合成多个PDF

主要代码

const puppeteer = require('puppeteer');
const fs = require('fs');
const path = require('path');

function readJSONFile(file) {
  return new Promise((resolve, reject) => {
    fs.readFile(file, 'utf8', (err, data) => {
      if (err) {
        reject(err);
        return;
      }
      try {
        const json = JSON.parse(data);
        resolve(json);
      } catch (error) {
        reject(error);
      }
    });
  });
}

async function autoScroll(page) {
  await page.evaluate(async () => {
    await new Promise((resolve, reject) => {
      (async()=>{
        window.scrollTo(0, 0);
        function scrollToBottom() {
          return new Promise((resolve, reject) => {
            const scrollInterval = 500; // 滚动间隔为 500 毫秒

            function handleScroll() {
              const scrollHeight = document.documentElement.scrollHeight;
              const windowHeight = window.innerHeight;
              const maxScrollTop = scrollHeight - windowHeight;

              if (window.scrollY >= maxScrollTop) {
                clearInterval(scrollTimer); // 停止定时器
                console.log("已滚动到页面底部");
                resolve(); // 解析 Promise
                return;
              }

              window.scrollBy({ top: 500, left: 0, behavior: 'smooth' });
            }

            // 启动定时器,每隔 500 毫秒执行一次滚动
            const scrollTimer = setInterval(handleScroll, scrollInterval);
          });
        }

        // 调用封装的函数
        await scrollToBottom()
        .then(() => {
          resolve()
          console.log("滚动完成,执行其他操作");
          // 在滚动完成后,可以在这里执行其他操作
        })
        .catch((error) => {
          resolve()
          console.log("滚动过程中出现错误:", error);
          // 在滚动过程中出现错误时,可以在这里处理错误
        });
      })()
    });
  });
}

function removeIllegalCharacters(filename) {
  // 非法字符包括 \ / : * ? " < > |
  // 以及文件名中的非打印字符和控制字符
  const illegalCharactersRegex = /[\\/:*?"<>|\x00-\x1F]/g;
  return filename.replace(illegalCharactersRegex, " ");
}

(async ()=>{
  console.time("total")
  const json = await readJSONFile('懒兔子.json');
// console.log(json);
//   const browser = await puppeteer.launch({ headless: true });
  const browser = await puppeteer.launch();
  const pagePromises = [];
  const PROMISE_MAX = 10 ;
  for (let i = 0; i < json.length; i++) {
    let item = json[i];
    let title = item.title;
    let url = item.content_url;
    // printPDFByUrl(item.title,item.url)
    const pagePromise = (async () => {
      let page = await browser.newPage();
      try {
        console.log(url)
        await page.goto(url, { waitUntil: 'networkidle0' });
        // 执行JavaScript脚本
        await page.evaluate(() => {
          // 在这里编写你的JavaScript代码,修改样式可映射到pdf文件
          // document.querySelector('#activity-name').style.color = 'red';
        });
        let fileName = removeIllegalCharacters(title) + ".pdf";
        // 滚动页面到底部
        await autoScroll(page);
        const pdfPath = path.resolve(`./pdf-file-3/${fileName}`);
        await page.pdf({ path: pdfPath, format: 'A4' });
        console.log(pdfPath, "保存成功")
      } catch (error) {
        console.error(error);
      } finally {
        await page.close();
      }
    })();

    pagePromises.push(pagePromise);

    if (pagePromises.length >= PROMISE_MAX || i === json.length - 1) {
      console.time(`pdf${i}`);
      await Promise.all(pagePromises);
      pagePromises.length = 0;
      console.timeEnd((`pdf${i}`))
    }
  }
  await browser.close();
  console.log("共",json.length, "篇文章","PROMISE的个数",PROMISE_MAX,);
  console.timeEnd("total")
})()
// 21

json格式数据文件

微信公众号文章的数据,放几个看看格式好了。至于如何爬取的,后面再更。

[
  {
    "title": "咱们能关注点儿正经事儿么,比如:为什么现在很难找到好中医?",
    "wechat_account_name": "懒兔子",
    "publish_time": "2015-09-14",
    "content_url": "http://mp.weixin.qq.com/s?__biz=MzU0MTA3ODk2NQ==&mid=2247487026&idx=1&sn=c853f6148faebc3c2a47484e64aeae78&chksm=fb2e2ae8cc59a3fe2e4fb89d4358640058960098b8f5720d844d9381750f1ca138f9e19f73e7&scene=27#wechat_redirect",
    "cover": "http://mmbiz.qpic.cn/mmbiz/GFhWvdCB5NCqjekoZYh7PwYaTTyD7C1xVibmpWc08TAO5pITDAGnuiceKoIDR34nh8gUdIJSRA9AAPusDfbrNUsA/0?wx_fmt=jpeg"
  },
  {
    "title": "子午流注——经络的值班表而已。节假日不休息",
    "wechat_account_name": "懒兔子",
    "publish_time": "2015-09-15",
    "content_url": "http://mp.weixin.qq.com/s?__biz=MzU0MTA3ODk2NQ==&mid=2247487025&idx=1&sn=2534cb7ba955034d5fea39b5124964c9&chksm=fb2e2aebcc59a3fd503fb39dec59a47921a2d375daf5c67b305b3f5f8da97f37af12e0b573ea&scene=27#wechat_redirect",
    "cover": "http://mmbiz.qpic.cn/mmbiz/GFhWvdCB5NDl6fHmdvz25r6qaXngpddm5pHgKCBMmKvLgEWN3HjFnuBzxFNAVWFdTEtMO4RAWHRvk9TibgCiaQZQ/0?wx_fmt=jpeg"
  },
{
    "title": "子午流注(二)——肺与大肠是好基友",
    "wechat_account_name": "懒兔子",
    "publish_time": "2015-09-16",
    "content_url": "http://mp.weixin.qq.com/s?__biz=MzU0MTA3ODk2NQ==&mid=2247487024&idx=1&sn=93581ddc25912a54cf091427d389e935&chksm=fb2e2aeacc59a3fcbab08c88ec9b8a6801a0e75a5c11e446979a419d7bc5a49d3901291389fd&scene=27#wechat_redirect",
    "cover": "http://mmbiz.qpic.cn/mmbiz/GFhWvdCB5NAa8XzicWwsqLqPiaibLpC59Xx2LMlJTJCTdeEuLTHI5sh1vWicA5PuoZqFez85vqkupRSdPXOyoeCmUA/0?wx_fmt=jpeg"
  },
  {
    "title": "子午流注(三)——脾胃的那点儿事儿",
    "wechat_account_name": "懒兔子",
    "publish_time": "2015-09-17",
    "content_url": "http://mp.weixin.qq.com/s?__biz=MzU0MTA3ODk2NQ==&mid=2247487023&idx=1&sn=ef3c526bc8ebf8d4f577752cfe30d147&chksm=fb2e2af5cc59a3e3dbcb0732e6d30cf434fba96036ffec49ef5c19bc8c4cb7d0ea5ec603b254&scene=27#wechat_redirect",
    "cover": "http://mmbiz.qpic.cn/mmbiz/GFhWvdCB5NBUZIrsArLctVoBvfIStOHEKEPk1d1p2EsAicBd5mzpXBINdwFG5W2Tv07O1mibiaC0N7XuqJl4mmw7Q/0?wx_fmt=jpeg"
  }
]

执行结果

先说结论: 我电脑的设置PROMISE_MAX最佳数量为10-15,再多CPU就满了,可以自行根据自己的cpu设置。

共 226 篇文章 PROMISE的个数 20
total: 5:38.438 (m:ss.mmm)

共 226 篇文章 PROMISE的个数 10
total: 6:05.889 (m:ss.mmm)

共 51 篇文章 PROMISE的个数 10
total: 1:01.928 (m:ss.mmm)

共 51 篇文章 PROMISE的个数 5
total: 1:04.819 (m:ss.mmm)

共 51 篇文章 PROMISE的个数 2
total: 1:56.683 (m:ss.mmm)

注意事项

1,保存路径的文件夹需要,预先创建,
2,json数据文件的路径正确

3,json数据文件的格式正确
4,puppeteer的正确安装。

结语

大家需求量大的话,考虑封装个美美的UI

[/md]

免费评分

参与人数 14吾爱币 +13 热心值 +13 收起 理由
丁大狗 + 1 + 1 我很赞同!
snow_melody + 1 + 1 谢谢@Thanks!
米老头 + 1 + 1 鼓励转贴优秀软件安全工具和文档!
leo580 + 1 点赞楼主,期待楼主封装的美美的UI版!:loveliness:
q7634356 + 1 + 1 小白需求~美美的ui
lwd871209 + 1 + 1 我很赞同!
静静想我1970 + 1 + 1 需求大,必须大,美美UI,GKD
tail88 + 1 + 1 谢谢@Thanks!
uc081123 + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
开心熊猫741 + 1 + 1 还请打包
cao666888 + 1 还请打包
horsebojack + 1 + 1 还请打包ui 谢谢@Thanks!
风陵渡 + 1 + 1 谢谢@Thanks!
moonalong8 + 1 + 1 谢谢@Thanks!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

moonalong8 发表于 2023-8-3 19:57
有需求~美美的ui
风陵渡 发表于 2023-8-3 21:39
yee365 发表于 2023-8-3 22:26
头像被屏蔽
moruye 发表于 2023-8-3 22:32
提示: 作者被禁止或删除 内容自动屏蔽
ccber 发表于 2023-8-3 22:46
介绍一下原理,或者给个注释呗。我想学习
mormas 发表于 2023-8-4 07:45
功能很好,希望楼主继续加油完善。
yuexian 发表于 2023-8-4 07:46
有需要,还请打包。
zyw_zjk 发表于 2023-8-4 08:03
感谢分享,坐等打包。
dylabor 发表于 2023-8-4 08:13
感谢分享,坐等打包。
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-24 20:05

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表