如何在离开当前页面之前拦截Puppeteer中的请求?

Mar*_*kát 12 puppeteer

用例:

我们需要从页面中捕获所有出站路由。其中一些可能不是使用链接元素实现的,<a src="...">而是通过一些 javascript 代码或 as GET/POST表单实现的。

幻影JS:

在 Phantom 中,我们使用onNavigationRequested回调来做到这一点。我们只需单击某个选择器定义的所有元素,并用于onNavigationRequested捕获目标 url 和可能的方法或表单中的 POST 数据,然后取消该导航事件。

傀儡师:

我试过请求拦截,但此时请求被拦截,当前页面已经丢失,所以我不得不回去。


当浏览器仍在触发事件的页面上时,有没有办法捕获导航事件并停止它?

谢谢你。

小智 14

您可以执行以下操作。

await page.setRequestInterception(true);
page.on('request', request => {
  if (request.resourceType() === 'image')
    request.abort();
  else
    request.continue();
});
Run Code Online (Sandbox Code Playgroud)

这里的例子:

https://github.com/GoogleChrome/puppeteer/blob/master/examples/block-images.js

此处列出了可用的资源类型:

https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#requestresourcetype


Mar*_*kát 6

所以我终于发现了不需要浏览器扩展的解决方案,因此可以在无头模式下工作:

感谢这个人:https : //github.com/GoogleChrome/puppeteer/issues/823#issuecomment-467408640

page.on('request', req => {
  if (req.isNavigationRequest() && req.frame() === page.mainFrame() && req.url() !== url) {
    // no redirect chain means the navigation is caused by setting `location.href`
    req.respond(req.redirectChain().length
      ? { body: '' } // prevent 301/302 redirect
      : { status: 204 } // prevent navigation by js
    )
  } else {
    req.continue()
  }
})
Run Code Online (Sandbox Code Playgroud)

编辑:我们已向实现此功能的 Apify SDK 添加了辅助函数 - https://sdk.apify.com/docs/api/puppeteer#puppeteer.enqueueLinksByClickingElements

这是整个源代码:

https://github.com/apifytech/apify-js/blob/master/src/enqueue_links/click_elements.js

它稍微复杂一些,因为它不仅需要拦截请求,还需要捕获新打开的窗口等。


Bob*_*ngh 1

page.setRequestInterception(true);该文档在这里有一个非常详尽的示例: https: //github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#pagesetrequestinterceptionvalue。确保添加一些逻辑,如示例(及下面)中所示,它们避免图像请求。您将捕获它,然后中止每个请求。

page.on('request', interceptedRequest => {
     if (interceptedRequest.url.endsWith('.png') || 
                              interceptedRequest.url.endsWith('.jpg'))
         interceptedRequest.abort();
     else
         interceptedRequest.continue();
});
Run Code Online (Sandbox Code Playgroud)