加载动态网页与Puppeteer工作在本地主机,但不Heroku



Node.js应用,带有Express,部署在Heroku上。它只是动态网页。加载静态网页可以正常工作。

加载动态网页工作在本地主机,但在Heroku它抛出我code=H12,desc="Request timeout",service=30000ms,status=503

此外,在执行heroku restart或进行部署之后,似乎总是有一个status=200的实例只加载动态网页的静态部分。

日志截图。


我尝试了以下方法,这些方法在Heroku(如Error R14 (Memory quota exceeded)code=H13 desc="Connection closed without response")上部署时都导致了相同或其他意想不到的结果:

  • 切换我正在使用的木偶英雄构建包。我已经尝试了本故障排除指南和这条评论中提到的那些。
  • 在Puppeteer的launch参数中添加headless: true
  • 在Puppeteer的launch参数的args中增加--no-sandbox,--disable-setuid-sandbox,--single-process--no-zygote标志。(参考:此评论&这个评论)
  • 将Puppeteer的goto函数中的waitUntil参数设置为domcontentloadednetworkidle0networkidle2。(参考:此评论)
  • 在Puppeteergoto函数中传递timeout参数;我特别尝试了3000060000,以及0
  • 使用waitForSelector函数
  • 清除Heroku的构建缓存,按照本文。
  • 在控制台中打印url变量(参见下面的代码)。输出符合预期

我已经观察到:

  • 使用我现在拥有的代码(见下文),try-catch-finally块从未捕获任何错误。它总是以下之一:我得到一个不完整的结果(请求的动态网页的静态部分),应用程序崩溃(code=H13 desc="Connection closed without response")。所以我没有能够从catch块内的控制台中打印exception中得到任何东西。

关于如何使其工作的任何想法?

const app = express();
const puppeteer = require("puppeteer");
let port = process.env.PORT || 3000;
let browser;
...
app.listen(port, async() => {
browser = await puppeteer
.launch({
timeout: 0,
headless: true,
args: [
"--no-sandbox",
"--disable-setuid-sandbox",
"--single-process",
"--no-zygote",
],
});
});
...
app.get("/appropriate-route-name", async (req, res) => {
let url = req.query.url;
let page = await browser.newPage();
try {
await page.goto(url, {
waitUntil: "networkidle2",
});
res.send({ data: await page.content() });
} catch (exception) {
res.send({ data: null });
} finally {
await browser.close();
}
}

能够通过使用user-agents使其工作。动态页面现在在Heroku上加载得很好;请求不再每次都超时了。

const app = express();
const puppeteer = require("puppeteer");
let port = process.env.PORT || 3000;
var userAgent = require("user-agents");
...
app.get("/route-name", async (req, res) => {
let url = req.query.url;
let browser = await puppeteer.launch({
args: ["--no-sandbox"],
});
let page = await browser.newPage();
try {
await page.setUserAgent(userAgent.toString()); // added this
await page.goto(url, {
timeout: 30000,
waitUntil: "newtorkidle2", // or "networkidle0", depending on what you need
});
res.send({ data: await page.content() });
} catch (e) {
res.send({ data: null });
} finally {
await browser.close();
}
});