Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

微信公众号文章生成 pdf #60

Open
imfenghuang opened this issue Aug 21, 2024 · 0 comments
Open

微信公众号文章生成 pdf #60

imfenghuang opened this issue Aug 21, 2024 · 0 comments

Comments

@imfenghuang
Copy link
Owner

imfenghuang commented Aug 21, 2024

使用 puppeteer 将微信公众号文章网页生成 pdf 进行保存。推而广之,其他网页生成 pdf 原理也是一致的。

import puppeteer from "puppeteer";

// 自动滚动
async function autoScroll(page, options = {}) {
  const {
    distance: _distance = undefined,
    toScrollHeight = 2 ** 32 - 1,
    frequency = 100,
    step = 3,
  } = options;
  let distance = _distance;
  if (_distance === undefined) {
    distance = (await page.evaluate(() => window.innerHeight)) / step;
  }
  await page.evaluate(
    async ({ distance, toScrollHeight, frequency }) => {
      await new Promise((resolve, reject) => {
        let totalHeight = 0;
        const timer = setInterval(
          ([distanceTime, toScrollHeightTime]) => {
            const scrollHeight = document.body.scrollHeight;
            window.scrollBy(0, distanceTime);
            totalHeight += distanceTime;

            if (
              totalHeight > scrollHeight ||
              totalHeight > toScrollHeightTime
            ) {
              clearInterval(timer);
              resolve();
            }
          },
          frequency,
          [distance, toScrollHeight]
        );
      });
    },
    { distance, toScrollHeight, frequency }
  );
}

function sleep(wait = 300) {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve();
    }, wait);
  });
}

async function url2pdf(url, options = {}) {
  const {
    sleep: _sleep,
    mediaType,
    addStyleTagOption,
    gotoOption,
    ...rest
  } = options;

  const browser = await puppeteer.launch({
    headless: true,
  });

  const page = await browser.newPage();
  if (mediaType === "screen") {
    await page.emulateMediaType("screen");
  }

  await page.goto(
    url,
    gotoOption ?? {
      waitUntil: "networkidle0",
    }
  );
  await page.addStyleTag(
    addStyleTagOption ?? {
      content: `
        @page {
            margin: 2cm 0 0 0;
        }
    `,
    }
  );

  await autoScroll(page);
  await sleep(_sleep ?? 2000);
  await page.pdf(
    Object.assign(
      {
        path: `pdf-${Date.now()}.pdf`,
        format: "A4",
        printBackground: true, // 输出背景色,false 时,背景样式无法输出到 pdf 上
      },
      rest
    )
  );
  await browser.close();
}

// 微信公众号文章链接
const url = "https://mp.weixin.qq.com/s/xxx";
url2pdf(url);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant