Har*_*mer 5 javascript events xmlhttprequest node.js puppeteer
我的 Node.js puppeteer 脚本成功地填写了一个表单,但在返回修改后的页面内容之前,页面有时只接受元素上的“单击”事件。这是脚本:
const fetchContracts = async (url) => {
const browser = await pupeteer.launch({ headless: true, args: ['--no-sandbox', '--disable-setuid-sandbox']});
const page = await browser.newPage();
const pendingXHR = new PendingXHR(page);
await page.goto(url, { waitUntil: 'networkidle2' });
await Promise.all([
page.click("#agree_statement"),
page.waitForNavigation()
]);
await page.click(".form-check-input");
await Promise.all([
page.click(".btn-primary"),
page.waitForNavigation()
]);
/// MY PROBLEM OCCURS HERE
/// Sometimes these clicks do not register....
await page.click('#filedReports th:nth-child(5)')
await pendingXHR.waitForAllXhrFinished();
await page.click('#filedReports th:nth-child(5)');
await pendingXHR.waitForAllXhrFinished();
/// And my bot skips directly here....
let html = await page.content();
await page.close();
await browser.close();
return html;
Run Code Online (Sandbox Code Playgroud)
}
“pendingXHR”模块是一个导入,我从这个库的代码中把它放在最上面:
const { PendingXHR } = require('pending-xhr-puppeteer');
Run Code Online (Sandbox Code Playgroud)
该脚本在我的本地计算机上运行,并且在我将脚本上传到 Digital Ocean 时有时会运行。根据我正在抓取的页面,这些点击会启动 XHR 请求,我正在尝试等待。这里有证据:
所以我的问题是:
为什么这些点击不会注册,即使我正在等待它们并等待 XHR 请求,然后才从页面中提取 html 然后返回?为什么与此不一致,有时点击注册,有时不注册?
谢谢你的帮助。
简短回答:单击将导致 AJAX 请求延迟,因此pendingXHR.waitForAllXhrFinished()
将立即解决,因为执行函数时没有发生任何请求。page.waitForResponse('.../data/')
代替使用。
您期望发生以下事件过程:
pendingXHR.waitForAllXhrFinished()
被处决pendingXHR.waitForAllXhrFinished()
决心page.content()
被处决问题是您正在使用的库 (PendingXHR)等待当前待处理的请求,并在它们解决后立即解决。这在我能想到的两种情况下不起作用:
1.AJAX请求异步启动
在这种情况下,事件的顺序将如下所示:
pendingXHR.waitForAllXhrFinished()
被处决pendingXHR.waitForAllXhrFinished()
立即解决(因为没有请求)page.content()
被处决(太早了!)2、UI异步修改表
在这种情况下,事件的顺序将如下所示:
pendingXHR.waitForAllXhrFinished()
被处决pendingXHR.waitForAllXhrFinished()
决心page.content()
(太早了!)不一致的发生是因为有时事件的顺序可能是正确的,因为在这种情况下,毫秒可以决定首先发生什么。
在不查看页面代码的情况下,我无法确定是哪种情况(实际上可能是两种情况),但我猜这是第一个,因为我完全可以看到表库等待任何双击/拖动/等等。在发出 AJAX 请求之前发生。
第一个问题可以通过使用来解决,page.waitForResponse
因为pendingXHR.waitForAllXhrFinished
这可以确保请求data/
确实发生了。
修复第二种情况(如果有必要)并不是那么简单,但是可以通过使用引入固定的等待时间来完成page.waitFor(10)
。
通过修复这两种情况,新代码如下所示:
await Promise.all([ // wait for the response to happen and click
page.waitForResponse('.../data/'), // use the actual URL here
page.click('...'),
]);
await page.waitFor(10); // wait for any asynchronous rerenders that might happen
let html = await page.content();
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
807 次 |
最近记录: |