我正在研究一些 Puppeteer 支持的网站分析,并且确实需要在页面上列出所有事件。
使用“普通” JavaScript 很容易,所以我想我可以在 Puppeteer 中评估它并完成其他任务。
好吧 - 这并不容易,例如“getEventListeners”不起作用。所以下面的代码不起作用(但如果我采用被评估的代码,请将其复制到浏览器的控制台并运行 - 它运行良好);
exports.getDomEventsOnElements = function (page) {
return new Promise(async (resolve, reject) => {
try {
let events = await page.evaluate(() => {
let eventsInDom = [];
const elems = document.querySelectorAll('*');
for(i = 0; i < elems.length; i++){
const element = elems[i];
const allEventsPerEl = getEventListeners(element);
if(allEventsPerEl){
const filteredEvents = Object.keys(allEventsPerEl).map(function(k) {
return { event: k, listeners: allEventsPerEl[k] };
})
if(filteredEvents.length > 0){
eventsInDom.push({
el: element,
ev: filteredEvents
})
}
}
}
return eventsInDom;
})
resolve(events);
} catch (e) {
reject(e);
}
})
}
我已经进一步调查,看起来这在 Puppeteer 中不起作用,甚至尝试过使用好的旧 JQuery const events = $._data( element[0], 'events' );
,但它也不起作用。
然后我偶然发现了 Chrome DevTools 协议(CDP),应该可以通过预先定义一个元素来获得它;
const cdp = await page.target().createCDPSession();
const INCLUDE_FN = true;
const { result: {objectId} } = await cdp.send('Runtime.evaluate', {
expression: 'foo',
objectGroup: INCLUDE_FN ?
'provided' : // will include fn
'' // wont include fn
});
const listeners = await cdp.send('DOMDebugger.getEventListeners', { objectId });
console.dir(listeners, { depth: null });
(来源:https ://github.com/puppeteer/puppeteer/issues/3349 )
但是当我想检查每个 DOM 元素的事件并将它们添加到数组时,这看起来太复杂了。我怀疑有比循环页面元素并为每个元素运行 CDP 更好的方法。或者更好地说-我希望:)
有任何想法吗?
我只想拥有一个包含(JS)事件的所有元素的数组,例如:
let allEventsOnThePage : [
{el: "blutton", events : ["click"]},
{el: "input", events : ["click", "blur", "focus"]},
/* you get the picture */
];