rest - 从 rest api 调用 puppeteer
问题描述
从休息端点调用 puppeteer 的适当方法是什么?
路由.js
const express = require('express');
const PuppeteerController = require('../controllers/puppetter');
const router = express.Router();
router.post('/getPath', PuppeteerController.getPage);
控制器.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'
});
}
}
扫描仪.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'
}
}
这是最好的方法吗?如果我对该端点有多次点击,我会担心性能。
解决方案
是的,可以这样做。我建议使用 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.');
});
})();
推荐阅读
- c - 线程初始化
- python - Python:从数据框列值中删除特定字符
- pywin32 - ImportError:DLL 加载失败:找不到指定的模块。对于 Win32gui
- react-native - 带有 useEffect 的 useFocusEffect 随机返回警告“不支持 'route' 对象的属性”
- c# - 为什么会话保存到数据库但没有返回?
- javascript - 同一文件中的 JavaScript 函数互不可见?
- python - 如何使用 PyTube 下载没有音频的 youtube 视频(mp4,质量好)
- javascript - 如何在 Map 中使用 `(K | V)[][]` 作为 `ReadonlyArray<[K, V]>`?
- javascript - 上传图片在codeigniter 3中不起作用
- python - cv2.resize() - 错误 - OpenCV(4.2.0) - 错误:(-215:Assertion failed) - 循环图像