如何用Puppeteer爬取h2标签后的所有关联元素?
解决Puppeteer爬取两种不同DOM结构的演员标签问题
问题分析
你的代码只处理了**h2「Movie Star」后第一个兄弟元素(单个h3)**里的a标签,当遇到第二种结构(多个h3各包含一个a标签)时,h2Element.nextElementSibling只会获取到第一个h3,自然只能拿到第一条数据。
解决方案
需要修改选择逻辑,覆盖h2之后所有包含目标a标签的h3元素,以下是两种可行的实现方式:
方式1:遍历h2后的所有兄弟节点
直接遍历h2元素之后的所有同级节点,筛选出h3标签并提取其中的a标签:
let actorLinks = []; let actors = []; h2Elements.forEach((h2Element) => { // 处理文本空格问题,避免匹配失败 if (h2Element.textContent.trim() === 'Movie Star') { let nextSibling = h2Element.nextElementSibling; // 遍历后续所有兄弟节点 while (nextSibling) { // 只处理h3标签 if (nextSibling.tagName === 'H3') { const targetATags = nextSibling.querySelectorAll('a[rel="tag"]'); targetATags.forEach(tag => { actorLinks.push(tag.href.trim()); actors.push(tag.textContent.trim()); }); } else { // 假设演员标签都在h2后的连续h3中,遇到非h3则停止遍历 break; } nextSibling = nextSibling.nextElementSibling; } } });
方式2:通过父容器定位所有目标h3
利用h2的父容器,选择容器内所有在h2之后的h3元素:
let actorLinks = []; let actors = []; h2Elements.forEach((h2Element) => { if (h2Element.textContent.trim() === 'Movie Star') { const parentContainer = h2Element.parentElement; const allH3InContainer = parentContainer.querySelectorAll('h3'); let isAfterTargetH2 = false; allH3InContainer.forEach(h3 => { // 判断当前h3是否在目标h2之后 if (!isAfterTargetH2) { isAfterTargetH2 = h2Element.compareDocumentPosition(h3) & Node.DOCUMENT_POSITION_FOLLOWING; } // 提取h3中的目标a标签 if (isAfterTargetH2) { const targetATag = h3.querySelector('a[rel="tag"]'); if (targetATag) { actorLinks.push(targetATag.href.trim()); actors.push(targetATag.textContent.trim()); } } }); } });
关键改动说明
- 初始化
actorLinks和actors为空数组,而非null,避免后续操作报错 - 增加
trim()处理文本和链接,消除多余空格的影响 - 不再局限于第一个兄弟元素,而是覆盖所有符合条件的h3节点
内容的提问来源于stack exchange,提问作者ZawKey
相关产品推荐
相关产品推荐

