使用mutantObserver检测DOM中的新节点,并通过puppetteer中的page.exposeFunction返回elementHandle。
有没有人知道是否可以使用mutationObserver,以便当DOM的一部分中创建新的子对象时,它会检测到它并将elementHandle对象作为结果发送给puppeteerexposeFunction方法进行处理?我正在使用它来提取添加的每个节点的上下文,并继续对它进行刮取。如果有人能帮助我,我将不胜感激。现在我已经尝试了以下方法:(选择器是每张牌的选择器)。
await page.exposeFunction('getItem', function(element) {
// const elementHandle = await page.evaluateHandle((el) => el, node);
console.log('Se agrego una tarjeta a la cola.'.blue);
console.log(element);
tarjetaQueue.push(element);
});
await page.evaluate((selector, page) => {
// Observar el contenedor de tarjetas para detectar nuevas tarjetas agregadas al DOM
const observer = new MutationObserver(async mutationsList => {
console.log(selector);
try{
for (const mutation of mutationsList) {
if (mutation.type === 'childList' && mutation.addedNodes.length) {
for (const node of mutation.addedNodes) {
const element = node.querySelector(selector);
getItem(element);
}
}
}
} catch (error) {
console.log("Error en mutation observer. ".red + error);
return null;
}
}, selector, page);
try{
const contenedorFeed = document.querySelector('#sections[section-identifier="comment-item-section"]:not([static-comments-header]) #contents.style-scope.ytd-item-section-renderer');
observer.observe(contenedorFeed, { childList: true });
}catch(error){
console.log("No se encontraron TARJETONAS. ".red + error);
}
});
我需要从每个注解中得到一个elementHandle,就像通过执行以下操作获得的一样:elementHandle = await comment.$(selector),我不知道这是否可以通过mutantObserver实现,因为我的代码使用了那些
1条答案
按热度按时间p8h8hvxi1#
你的目标并不完全清楚,更多的背景将有助于避免xy问题。您正在询问尝试的解决方案,但它可能不是解决潜在问题的最佳方法,可能是抓取一些数据。但根据讨论,我有几点意见,可以尝试为您指出一个更可行的方法:
exposeFunction
不能处理DOM节点。DOM节点是不可序列化的,因此当您尝试在Node中使用它们时,它们将反序列化为空对象。99.9%的情况下,您不需要此功能。如果您确实想使用它将数据传递到Node,请在浏览器中处理数据,以便它是可序列化的。MutationObserver
之上提供了方便的 Package 器,如waitForFunction
和waitForSelector
,因此99.9%的时间使用Puppeteer库,而不是安装自己的低级观察器。即使你真的需要滚动自己的监听器,你也可以使用requestAnimationFrame
或setTimeout
作为轮询循环,这在语法上更简单,假设性能不是关键的(你可以从RAF开始,然后升级到观察者,一旦你有了基本的工作)。$$eval
和$eval
是提取数据的更直接的方法。现在,YouTube是出了名的烦人刮,有成千上万的评论,你所显示的示例页面。我建议尽可能避免使用它们的DOM,在本例中,这似乎是可能的。您可以监视网络请求并捕获向下滚动页面时返回的JSON有效负载。我在滚动时删除DOM节点,以避免注解列表变长时性能下降。
我使用的是一个简单的测试用例,因此脚本将在合理的时间内完成。您可能希望在工作时将数据写入磁盘,然后在以后脱机处理它。我加入了一些预处理,以展示如何遍历结果结构以获得所需的任何数据。
有几个超时,不是很好的练习,但是我没有时间用真正的 predicate 来替换它们。我以后再谈这个。
请注意,由于issue #10033,您需要避免使用18.2.1和20.0.0之间的Puppeteer版本来自动化YouTube。