JSDOM查询NodeList为空:动态内容抓取策略与Puppeteer实践

jsdom查询nodelist为空:动态内容抓取策略与puppeteer实践

在使用JSDOM和Axios进行网页抓取时,有时会遇到`querySelectorAll`返回空`NodeList`的问题,尤其当目标元素(如`

`)是网站动态加载时。这通常是因为JSDOM仅处理静态HTML,无法模拟浏览器执行JavaScript。本文将深入探讨此问题的原因,并提供使用Puppeteer这一无头浏览器工具的解决方案,以有效抓取动态渲染的网页内容,确保获取预期的DOM元素。

网页抓取中NodeList为空的常见问题

在使用axios获取网页HTML内容,并结合JSDOM解析DOM时,开发者可能会遇到一个令人困惑的现象:通过querySelector或querySelectorAll查询某个元素(例如ul下的li元素),尽管在浏览器开发者工具中这些元素清晰可见,但在代码中返回的NodeList却是空的,或者其length属性为0。

例如,针对以下HTML结构:

尝试使用以下JSDOM代码抓取li元素:

// 假设 res.data 包含了上述HTMLconst dom = new JSDOM(res.data);const ulist = dom.window.document.querySelector('#download-options > .panel-body > ul');// ulist 可能会正确返回 HTMLUListElement {}// ulist.childElementCount 可能会返回 1 (表示有一个子元素,即文本节点或注释)const lists = ulist.querySelectorAll('li');// 此时 lists.length 却返回 0,而非预期的 3

这种情况下,ulist本身可能被正确选中,但其内部的li元素却无法通过querySelectorAll获取。

问题根源:静态抓取与动态渲染

这个问题的核心在于网页内容的加载方式。axios作为一个HTTP客户端,它只能获取服务器首次响应的原始HTML字符串。JSDOM则是一个纯JavaScript的DOM实现,它根据这个原始HTML字符串构建DOM树,但它不具备浏览器环境,无法执行页面中的JavaScript代码。

许多现代网站会利用JavaScript在页面加载完成后动态地生成、修改或插入DOM元素。这些动态内容可能包括:

通过AJAX请求获取数据后渲染列表项。基于用户行为或设备状态调整页面布局。通过前端框架(如React, Vue, Angular)进行客户端渲染。网站可能出于反爬虫目的,延迟加载关键内容,或依赖于特定的Cookie、Session或用户代理来显示完整内容。

当axios获取到的是一个“骨架屏”HTML,而li元素是由后续JavaScript代码动态填充时,JSDOM处理的DOM树自然就不会包含这些动态生成的li元素,从而导致querySelectorAll返回空结果。在浏览器开发者工具中能看到这些元素,是因为浏览器完整执行了所有JavaScript,渲染出了最终的DOM。

解决方案:使用Puppeteer处理动态内容

为了解决JSDOM无法处理动态内容的问题,我们需要一个能够模拟真实浏览器环境的工具。Puppeteer是一个由Google开发的Node.js库,它提供了一套高级API来通过DevTools协议控制Chrome或Chromium浏览器。这意味着Puppeteer能够:

加载网页并执行所有JavaScript。等待异步内容加载完成。模拟用户交互(点击、输入等)。截取屏幕截图或生成PDF。获取最终渲染的DOM内容。

Puppeteer实践示例

以下代码展示了如何使用Puppeteer来抓取动态加载的li元素:

const puppeteer = require('puppeteer');(async () => {  // 1. 启动无头浏览器实例  // headless: true 表示在后台运行浏览器,不显示UI界面  const browser = await puppeteer.launch({ headless: true });  const page = await browser.newPage();  // 2. 访问网站首页 (可选,但可能解决某些网站的缓存/Cookie问题)  // 某些网站会根据首次访问设置Cookie或Session,影响后续页面的内容  await page.goto('http://example.com', { waitUntil: 'domcontentloaded' }); // 等待DOM加载完成  // 3. 访问目标页面  await page.goto('https://example.com/targetpage', { waitUntil: 'networkidle2' });   // waitUntil: 'networkidle2' 会等待网络连接空闲2秒,通常意味着页面所有资源已加载完毕  // 也可以使用 'domcontentloaded' 或 'load',具体取决于页面加载特性  // 4. 等待目标元素出现  // 这一步至关重要,确保动态加载的元素已经渲染到DOM中  await page.waitForSelector('#download-options li', { timeout: 5000 }); // 最多等待5秒  // 5. 查询元素并提取数据  // page.$ 用于查询单个元素  const ul = await page.$("#download-options ul");   // page.$$ 用于查询多个元素  const lis = await ul.$$("li");  console.log(`找到 ${lis.length} 个 li 元素。`);  // 6. 遍历并提取每个 li 内部的 a 标签的 href 属性  for await (const li of lis) {    const a = await li.$('a'); // 在每个 li 元素内部查询 a 标签    if (a) {      // 使用 evaluate 方法在浏览器环境中执行JS代码来获取属性值      const hrefValue = await a.evaluate((el) => el.getAttribute('href'));      console.log(`链接地址: ${hrefValue}`);    }  }  // 7. 关闭浏览器实例  await browser.close();})();

代码解析与注意事项

puppeteer.launch({ headless: true }): 启动一个Chromium实例。headless: true表示无头模式,浏览器在后台运行,没有图形界面。在开发调试阶段,可以设置为false来观察浏览器行为。page.goto(url, { waitUntil: ‘networkidle2’ }): 导航到指定URL。waitUntil参数非常重要,它决定了Puppeteer何时认为页面加载完成。domcontentloaded: DOMContentLoaded事件触发时。load: load事件触发时。networkidle0: 当网络连接数变为0后持续至少500ms。networkidle2: 当网络连接数变为2后持续至少500ms。选择合适的waitUntil策略对于确保所有动态内容加载至关重要。networkidle2通常是一个比较稳妥的选择。page.waitForSelector(‘#download-options li’, { timeout: 5000 }): 这是解决动态内容问题的关键。它会暂停代码执行,直到指定的CSS选择器对应的元素出现在DOM中。如果元素在timeout时间内未出现,则会抛出错误。这确保了在尝试查询元素之前,它们已经被JavaScript渲染到页面上。page.$ 和 page.$$:page.$(selector): 类似于document.querySelector(),返回匹配的第一个ElementHandle对象。page.$$(selector): 类似于document.querySelectorAll(),返回所有匹配的ElementHandle对象数组。ElementHandle是Puppeteer对DOM元素的引用,它允许你在其上执行进一步的操作,如查询子元素或调用evaluate。element.evaluate((el) => el.getAttribute(‘href’)): evaluate方法允许你在浏览器上下文(即页面内部)执行一段JavaScript代码。这对于获取元素的属性、文本内容或执行更复杂的DOM操作非常有用,因为这些操作是在真实的浏览器环境中进行的。资源管理: 务必在抓取完成后调用browser.close()来关闭浏览器实例,释放系统资源。

总结

在进行网页抓取时,理解目标网站的内容加载机制至关重要。对于静态HTML内容,axios结合JSDOM是一个轻量且高效的选择。然而,一旦遇到由JavaScript动态渲染的内容,JSDOM就力不从心了。此时,Puppeteer作为无头浏览器自动化工具,能够完美模拟真实用户的浏览行为,执行页面JavaScript,并等待动态内容加载完成,从而成功抓取到完整的DOM结构和数据。正确选择工具并熟练运用page.waitForSelector等等待机制,是成功抓取动态网页内容的关键。

以上就是JSDOM查询NodeList为空:动态内容抓取策略与Puppeteer实践的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1596910.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2025年12月23日 11:34:59
下一篇 2025年12月23日 11:35:16

相关推荐

  • CSS样式未生效?排查你的CSS注释!

    本文旨在帮助开发者解决css样式部分生效的问题。通过分析一个实际案例,我们发现css注释的错误使用可能导致后续样式失效。本文将详细讲解正确的css注释语法,并提供排查类似问题的思路,确保你的css样式能够正确应用。 在进行前端开发时,有时会遇到CSS样式表中部分样式生效,而另一些样式却无法应用的情况…

    2025年12月23日
    000
  • 优化JavaScript滚动事件中的条件逻辑:实现元素精确显隐控制

    本文探讨了在javascript滚动事件中,如何通过精确的条件判断来控制网页元素的显示与隐藏,特别是在涉及多个滚动区间时。针对常见的条件逻辑错误,我们提出使用明确的范围判断来避免条件重叠,确保不同滚动位置下的元素行为符合预期,从而实现更稳定、可预测的用户界面交互。 在现代Web开发中,根据用户滚动页…

    2025年12月23日
    000
  • Nuxt Content 中禁用 Markdown 标题自动锚点链接的教程

    nuxt content v2 默认会将 markdown 和 html 标题(h2-h6)渲染为带有锚点链接的形式,这可能不符合所有内容展示需求。本教程将指导您如何通过修改 `nuxt.config.ts` 文件中的 `content.markdown.anchorlinks` 配置项,轻松禁用此…

    2025年12月23日
    000
  • 如何引用全局html_全局HTML文件(如header/footer)引用方法

    通过引用全局HTML文件可统一管理网页头部和底部,提升维护效率。具体方法包括:一、使用JavaScript动态加载外部HTML内容,适用于静态网站;二、利用iframe嵌入header和footer页面,结构清晰;三、采用服务端包含(SSI)指令在服务器合并文件,需配置.s%ignore_a_1%扩…

    2025年12月23日
    000
  • Windows中HTML文件为什么双击后直接在浏览器打开?

    双击HTML文件自动在%ignore_a_1%中打开,是因Windows通过注册表将.html扩展名关联至默认浏览器。系统识别文件扩展名并查询HKEY_CLASSES_ROOT.html项,定位程序标识符后启动对应浏览器进程,同时传递文件路径参数。用户可通过右键菜单更改默认应用,选择其他程序如Vis…

    2025年12月23日
    000
  • Linux Trilium笔记用CSS主题切换HTML学习模式

    Trilium Notes可通过自定义CSS和HTML实现学习模式:1. 在笔记子项中添加text/css类型笔记并编写样式,隐藏树状栏、工具栏,优化字体与布局;2. 创建text/html子笔记插入切换按钮,通过JavaScript动态控制学习模式开关;3. 可扩展深色模式、字体调节等功能,提升专…

    2025年12月23日
    000
  • html如何设置按键_HTML键盘按键事件(keydown/keyup)监听方法

    答案:通过JavaScript的addEventListener方法监听keydown和keyup事件,可实现对用户键盘输入的响应,支持全局或特定元素的按键监听,利用event.key或event.code获取键值,并可通过preventDefault限制特定按键输入;也可在HTML中使用onkey…

    2025年12月23日
    000
  • Mac用Raycast一键搜索HTML5新特性文档

    通过Raycast配置自定义脚本命令,一键打开MDN上HTML5特性文档页面;2. 将HTML5官方指南添加为浏览器书签,并利用Raycast书签搜索功能快速访问;3. 安装支持API的扩展,在Raycast中直接预览HTML5新特性摘要信息。 如果您希望在Mac上快速查找HTML5的最新特性文档,…

    2025年12月23日
    000
  • html网页转换器_html网页格式转换网页版

    html网页转换器入口地址是https://www.html-converter.com,该平台支持HTML转PDF、DOC等格式,无需安装软件,界面简洁,保留原排版,云端处理速度快,支持批量转换、无需登录、兼容主流浏览器,响应稳定且支持HTML5,提供预览与日志功能。 html网页转换器入口地址是…

    2025年12月23日
    000
  • Windows一键让CSS秒刷新HTML,改完立马看效果!

    使用Live Server、Webpack、Browsersync或Python+watchdog可实现CSS保存后页面自动更新。1、VS Code安装Live Server插件,右键HTML文件选择“Open with Live Server”即可实时刷新;2、Webpack搭配webpack-d…

    2025年12月23日
    000
  • 如何编辑html 按钮_HTML按钮(button)属性与样式编辑方法

    要创建或修改网页按钮,需编辑HTML属性与CSS样式:一、设置type、disabled、name和value等属性控制按钮行为;二、通过style属性添加内联样式实现快速外观调整;三、使用class引用外部或内部CSS类统一管理样式,提升复用性;四、利用:hover、:active和transit…

    2025年12月23日
    000
  • Mac神器Live Server,HTML+CSS改一行全局同步!

    使用Live Server可实现HTML/CSS修改后浏览器自动刷新。通过VS Code安装Live Server插件,右键文件选择“Open with Live Server”即可启动本地服务,默认在http://127.0.0.1:5500预览;可在设置中自定义端口和默认浏览器;项目中使用相对路…

    2025年12月23日
    000
  • Mac Parallels中Windows子系统共享HTML+CSS文件夹

    首先启用Parallels共享功能,选择Mac上的项目文件夹并开启共享;随后在Windows中通过“此电脑”访问映射的“Mac Home”网络驱动器,直接打开编辑HTML/CSS文件;建议同步剪贴板、使用统一存储路径并确保文件权限正确,以实现高效跨平台前端开发。 在 Mac 上使用 Parallel…

    2025年12月23日
    000
  • html如何快速输入_HTML代码快速输入(快捷键/工具)方法

    使用快捷键和工具可高效编写HTML代码。一、现代编辑器如VS Code支持语法高亮与自动补全,输入“li*5”创建五个列表项,“#header”生成id为header的div。三、自定义代码片段,如设置“finp”触发表单项结构,提升复用效率。四、借助HTML-CSS-JS.com等在线工具,通过表…

    2025年12月23日
    000
  • Windows11 Widgets面板添加HTML学习进度插件

    可通过Microsoft Edge侧边栏、第三方小工具或RSS订阅三种方式在Windows 11实现HTML学习进度展示。 如果您希望在Windows 11的Widgets面板中添加一个显示HTML学习进度的自定义插件,但发现系统原生不支持直接添加第三方HTML内容,可以通过变通方式实现信息展示。以…

    2025年12月23日
    000
  • Mac Ventura系统下TextEdit保存HTML默认UTF-8设置

    答案:在macOS Ventura的TextEdit中保存HTML文件时,需设置UTF-8编码以避免乱码。首先,手动导出时选择“纯文本”格式并勾选“使用UTF-8编码”;其次,通过“设置”→“打开和存储”中启用“存储时使用UTF-8编码”并取消自动转纯文本;最后,可使用终端命令defaults wr…

    2025年12月23日
    000
  • 在线HTML转换器手机入口 HTML转换器手机版工具试用

    在线HTML转换器手机入口为https://www.freeformatter.com/html-validator.html,用户可通过手机浏览器直接访问,无需下载应用;页面适配移动端,支持触控操作,可上传本地文件或粘贴代码进行HTML校验、格式化、编码转换与压缩;同时集成CSS、JS、JSON、…

    2025年12月23日
    000
  • Mac Gatekeeper阻止HTML运行脚本怎么允许?

    答案是调整安全性设置、移除隔离属性、修改浏览器配置或使用本地服务器。首先在“隐私与安全性”中允许被阻止的文件运行;接着用终端命令xattr -d com.apple.quarantine清除下载文件的隔离标记;然后检查Safari或更换Chrome/Firefox并确保JavaScript启用;最后…

    2025年12月23日
    000
  • Windows Anki卡片用CSS美化HTML5标签记忆效果

    通过CSS为Anki卡片中的HTML5标签设置语义化颜色、分组容器、悬停动画和正反面示例,可增强视觉层次与交互反馈,1. 结构类标签用蓝色、表单类用橙色、媒体类用绿色;2. 正面显示标签名,反面展示代码与说明;3. 添加hover缩放与阴影效果;4. 使用边框分组相关标签,提升记忆效率。 在Anki…

    2025年12月23日
    000
  • Ranger批量重命名,HTML+CSS成对改名超省时!

    使用Ranger结合正则表达式与脚本可高效批量重命名HTML/CSS配对文件。首先在Ranger中选中文件并进入Shift+R批量重命名模式,利用:%s/page-d+/newsection-/等正则统一替换;对于无规律命名,可编写Python脚本生成映射表并通过:pipe调用;序列化命名则通过模板…

    2025年12月23日
    000

发表回复

登录后才能评论
关注微信