从 Rest api 调用 puppeteer

xDG*_*xDG 3 api rest puppeteer

是从休息端点调用 puppeteer 的适当方法吗?

路由.js

const express = require('express');

const PuppeteerController = require('../controllers/puppetter');

const router = express.Router();

router.post('/getPath', PuppeteerController.getPage);
Run Code Online (Sandbox Code Playgroud)

控制器.js

async getPage(req, res) {
   try {
    let resp = await pageScanner.getPageContent(url);
    return res.status(200).send(resp);
   }
   catch(e) {
      return res.status(400).send({
        error: 'not-found'
      });
   }
}
Run Code Online (Sandbox Code Playgroud)

扫描仪.js

async getPageContent(url) {
   try {
      const browser = await puppeteer.launch({
        args: [
          '--no-sandbox',
          '--disable-setuid-sandbox',
          '--disable-dev-shm-usage',
          '--disable-accelerated-2d-canvas',
          '--disable-gpu'
        ]
      });
      const page = await browser.newPage();
      await page.setViewport({ width: 800, height: 600 });
      await page.goto(url);
      await page.waitFor(1000);
      const pageContent = await page.content();
      await page.close();
      await browser.close();
      return pageContent;
   } catch(e) {
     return 'No good'
   }
}
Run Code Online (Sandbox Code Playgroud)

这是最好的方法吗?我担心性能是否会多次命中该端点。

Tho*_*orf 6

是的,这是可以做到的。我建议使用 puppeteer 实例池来限制并行执行的数量。正如您已经注意到的,否则在大约同时传入 10 个请求的情况下,您可能会打开 10 个浏览器。

查看库puppeteer-cluster(免责声明:我是作者),它支持您的用例。

代码示例

我从文档中的“带有 Express 的最小屏幕截图服务器”示例中获取了代码,并根据您的用例进行了调整。该代码创建一个具有多个浏览器的集群(可以使用多少个并行实例,取决于计算机的 CPU/内存/吞吐量),并生成一个快速服务器来处理传入请求。爬取的 URL 由参数给出?url=...

const express = require('express');
const app = express();
const { Cluster } = require('puppeteer-cluster');

(async () => {
    const cluster = await Cluster.launch({
        concurrency: Cluster.CONCURRENCY_BROWSER,
        maxConcurrency: 4,
    });

    // setup the function to be executed for each request
    await cluster.task(async ({ page, data: url }) => {
        await page.goto('http://' + url);
        // ...
        return await page.content();
    });

    // setup server
    app.get('/', async function (req, res) { // expects URL to be given by ?url=...
        try {
            // run the task function for the URL
            const resp = await cluster.execute(req.query.url);
            // respond with the result
            res.status(200).send(resp);
        } catch (err) {
            // catch error
            res.end('Error: ' + err.message);
        }
    });

    app.listen(3000, function () {
        console.log('Server listening on port 3000.');
    });
})();
Run Code Online (Sandbox Code Playgroud)