使用 node/puppeteer/js 从直接下载 link 下载 pdf 文件

Downloading pdf files from direct download link using node/puppeteer/js

我需要从直接下载中下载大约 300 个文件 link。当直接在浏览器中打开 link 时,会触发自动 pdf 下载。该文件已下载,浏览器不会去任何地方。 link如下:

www.link.com/store/item/123

在link中,每次循环都会更改123部分。

我正在考虑使用 puppeteer(带 goto),但我想由于访问 link 会自动触发 pdf 的下载并且实际上并没有转到该页面,所以它失败了。

这是我尝试过的方法,但根本不起作用:

const links = ['123', '456'];
(async () => {
    const browser = await puppeteer.launch({
        headless: false //preferably would run with true
    });

    links.forEach( async link => {
        const page = await browser.newPage();
        await page.goto(
            linkBeginning + link
        );
    
        await browser.close();
    })
})();

我四处搜索,但我真的找不到这个具体案例,所有其他案例都更侧重于用户端或者在实际 link 中有目标文件(比如 xx/store/doc。 PDF)。不太确定这是否有所作为。我只需要一个脚本,可以一次性获取 pdf 文件 运行.

如果有人在 php/python 中有解决方案也可以,因为这只是一次性的事情。

编辑: 最终在 html

完成
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="sku.js"></script>

    <script>
        const linkStart = 'https://www.sols-europe.com/gb/pdfpublication/pdf/product/sku/';
        sku.forEach(element => {
            document.write('<a target = "_blank" class="click" href="' + linkStart + element.id +'">'+ element.id +'</a></br>')
        });
    </script>
</head>
<body></body>
</html>

<script>
    const clickInterval = setInterval(function () {
    const el = document.querySelector('.click:not(.clicked)');
    if(el){
        el.classList.add('clicked');
        el.click()
    } else {
        clearInterval(clickInterval);
    }    
}, 2000);

</script>

您将 browser.close() 放在循环内不是一件好事。
所以我把它移到 forEach 外面,改为 page.close()。

const links = ['123', '456']
const linkBeginning = 'https://www.link.com/store/item/'
;(async () => {
    const browser = await puppeteer.launch({
        headless: false //preferably would run with true
    })

    links.forEach( async link => {
        const page = await browser.newPage()
        const session = await page.target().createCDPSession()
        await session.send('Page.setDownloadBehavior', {
            behavior: 'allow',
            downloadPath: './pdf/'
        })
        await page.goto(linkBeginning + link)
    
        await page.close() // Don't use browser.close() inside loop
    })
    await browser.close() // Use here instead
})()

您不需要 puppeteer 来执行此操作,并且您可以在 NodeJS 中相当轻松地实现它:

import http from "https";
import fs from "fs";

(async () => {
  const skus = ["00548", "03575"];

  const filesPromiseArray = skus.map(
    (sku) =>
      new Promise((resolve, reject) => {
        const file = fs.createWriteStream(`${sku}.pdf`);
        const request = http.get(`https://www.sols-europe.com/gb/pdfpublication/pdf/product/sku/${sku}`, (response) =>
          response.pipe(file)
        );
        file.on("finish", resolve);
        file.on("error", reject);
      })
  );
  try {
    await Promise.all(filesPromiseArray);
  } catch {
    console.log("There was an error downloading one of the files");
  }
})();

这段代码在做什么?

  1. 使用您的 skus 数组,我们正在使用 .map() 将它们转换为请求数组。
  2. .map() 中,我们正在创建一个 Promise,它将在文件完成下载时成功 (resolve),如果下载错误。
  3. 然后我们 await 我们刚刚创建的所有请求。如果其中之一失败,它将记录。

注:

如果您使用的是 CommonJS(package.json 中的 "type":"commonjs",),请将两个导入替换为:

const http = require('https');
const fs = require('fs');