如何使用Puppeteer同时获取标题及其同级段落等元素
实现方案
核心思路
利用Puppeteer的page.evaluate()在浏览器上下文直接操作DOM,遍历每个<h3>,收集其后续同级元素(直到下一个<h3>或父元素末尾),最终组装成符合要求的JSON数组。
注意:你提供的示例JSON存在重复键(多个
"p"),这不符合JSON规范,解析时会丢失数据。以下方案将同标签的内容转为数组(如"p": ["文本1", "文本2"]),生成合法有效的JSON结构。
代码实现
const puppeteer = require('puppeteer'); (async () => { // 启动浏览器 const browser = await puppeteer.launch(); const page = await browser.newPage(); // 加载目标页面(如果是本地HTML,改用page.setContent()) // await page.goto('https://your-target-url.com'); await page.setContent(` <div> <h3>Lorem ipsum dolor sit amet</h3> <p>First paragraph</p> <p>Second Paragraph</p> <h3>Lorem ipsum dolor sit amet</h3> <p>Second Paragraph</p> <p>Second Paragraph</p> <p>Second Paragraph</p> <h3>Lorem ipsum dolor sit amet</h3> <p>...</p> <p>...</p> <blockquote>...</blockquote> </div> `); // 在浏览器上下文处理DOM并生成结果 const result = await page.evaluate(() => { const sections = []; // 获取所有目标h3(假设都在div下) const headings = document.querySelectorAll('div > h3'); headings.forEach(heading => { const section = { h3: heading.textContent.trim() }; let nextEl = heading.nextElementSibling; // 遍历后续同级元素,直到遇到下一个h3或无元素 while (nextEl && nextEl.tagName !== 'H3') { const tag = nextEl.tagName.toLowerCase(); const text = nextEl.textContent.trim(); // 处理同标签重复的情况:转为数组存储 if (section[tag]) { if (!Array.isArray(section[tag])) { section[tag] = [section[tag]]; } section[tag].push(text); } else { section[tag] = text; } nextEl = nextEl.nextElementSibling; } sections.push(section); }); return sections; }); // 输出结果 console.log(JSON.stringify(result, null, 2)); await browser.close(); })();
运行结果
上述代码会生成如下合法JSON:
[ { "h3": "Lorem ipsum dolor sit amet", "p": [ "First paragraph", "Second Paragraph" ] }, { "h3": "Lorem ipsum dolor sit amet", "p": [ "Second Paragraph", "Second Paragraph", "Second Paragraph" ] }, { "h3": "Lorem ipsum dolor sit amet", "p": [ "...", "..." ], "blockquote": "..." } ]
可选调整
如果一定要保留你示例中的重复键结构(不推荐,因为JSON不允许),可以修改page.evaluate()内的逻辑,直接添加重复键,但需注意:这种JSON无法被标准解析器正确处理,后续使用会有问题。
内容的提问来源于stack exchange,提问作者jgcarrillo
相关产品推荐
相关产品推荐

