【发布时间】:2021-01-09 15:34:06
【问题描述】:
我有一个简单的 puppeteer 脚本,我在每月 5 美元的 digitalocean 液滴上运行。脚本如下。该脚本登录到电子商务网站,并不断刷新页面以查找特定交易(如果发现添加到购物车和结帐)。从监控图中可以看出,内存随着每个循环而增加,直到达到最大值,然后脚本崩溃。我认为这里的内存是 RAM,而不是存储空间。
谁能建议一个更好的方法来配置 puppeteer 脚本来解决这个问题?循环运行大约需要 5 秒,运行大约 12 小时,直到内存使用量增加到循环运行时间从每次运行 5 秒爬升到每次运行 30 秒的地步。然后最终内存达到最大值并导致脚本崩溃。
在每次运行中关闭并重新打开浏览器会解决内存问题吗? 是因为我将脚本作为一个永无止境的 .js 文件运行吗?
Droplet 内存截图
const puppeteer = require('puppeteer-extra')
puppeteer.use(require('puppeteer-extra-plugin-stealth')())
const fs = require('fs');
const performance = require('perf_hooks').performance;
(async () => {
const browser = await puppeteer.launch({
args: ['--no-sandbox'],
headless: true
})
const page = await browser.newPage()
//Login to page
await page.goto('https://example.com/login', {waitUntil: 'load', timeout: 0});
await page.type('[name=email]','xxx@xxx.com');
await page.click('button[type="submit"]');
await page.waitForTimeout('input[name=password]');
await page.type('[name=password]','xxx');
await page.click('button[type="submit"]');
var runcount = 0
var foundcount = 0
//loops always running after logging in
while(true){
var t0 = performance.now();
await page.goto('https://www.example.com/xxx', {waitUntil: 'load', timeout: 0});
//do some await page.$$eval here
runcount++;
var t1 = performance.now();
console.log("Run: " + runcount + " | Runtime: " + Math.floor((t1 - t0)/1000);
}
await browser.close()
})()
【问题讨论】:
-
我会说这是因为您的页面在没有被“发布”的情况下不断增长,我真的不知道 pupeteer 是如何工作的,但我会在 while 循环中创建一个新页面并在最后发布它。无论哪种方式,浏览器都在分配内存,或者页面在分配内存并且永远不会释放它。
-
我建议不要连续运行脚本,而是使用 Cron 作业每隔十分钟定期运行它。让 PuppeteerJS 浏览器会话运行这么长时间注定会以糟糕的方式结束,因为它会消耗大量内存。而且由于页面没有关闭,因此在此期间任何时候都无法释放内存,这会导致您的 RAM 使用率达到峰值水平。
-
谢谢,但是对于这个脚本,它需要快速连续运行,所以 10 分钟不是一个选项。
-
只是为了测试,你可以定期尝试
browser.createIncognitoBrowserContext()和browserContext.close()——如果罪魁祸首是一些历史/cookies/缓存增长,这可以缓解问题。 -
另外,您可以尝试
page.setRequestInterception()并阻止任何不需要的资源。尽管您加载的是同一个页面,但它可能会使用来自各种来源的大量广告,这会影响历史/cookies/缓存/会话等。
标签: javascript node.js puppeteer digital-ocean