如何使用JavaScript抓取包含级联下拉选单的动态网页数据
问题原因与解决方法
核心错误点
- 选择器使用错误:操作第一个配料下拉的代码错误复用了第二个方法下拉的选择器
str,没有使用定义好的str2,无法正确选中第一个下拉选项 - 下拉选中逻辑错误:直接点击
option元素不会触发select绑定的联动事件,前端的级联显示逻辑通常绑定在select的change事件上,需要主动修改select值后手动触发事件 - 没有等待DOM更新:级联显示、按钮点击后加载内容都需要等待异步渲染完成,操作后立刻读取内容还是初始状态
- 输出内容错误:最后打印的是
axios请求拿到的原始静态HTML,没有读取jsdom中动态更新后的DOM内容
修正后实现代码
const { data } = await axios.get(url); const dom = new JSDOM(data, { runScripts: "dangerously", resources: "usable", }); const { document } = dom.window; // 封装等待元素可操作的工具函数 function waitForElement(selector, timeout = 3000) { return new Promise((resolve, reject) => { const start = Date.now(); const timer = setInterval(() => { const el = document.querySelector(selector); // 元素存在且可见(display不是none) if (el && dom.window.getComputedStyle(el).display !== 'none') { clearInterval(timer); resolve(el); } if (Date.now() - start > timeout) { clearInterval(timer); reject(new Error(`元素${selector}加载超时`)); } }, 100); }); } try { // 1. 操作第一个配料下拉 const ingredientSelect = document.querySelector('#Ingredients'); // 设置选中值为01对应Ingredient1 ingredientSelect.value = '01'; // 手动触发change事件触发级联逻辑 ingredientSelect.dispatchEvent(new Event('change')); // 2. 等待第二个方法下拉可见后操作 const methodSelect = await waitForElement('#methods'); methodSelect.value = '05'; methodSelect.dispatchEvent(new Event('change')); // 3. 等待按钮可见后点击 const checkBtn = await waitForElement('#check'); checkBtn.click(); // 4. 等待菜谱内容加载完成后读取 await waitForElement('#recipe'); const recipeContent = document.querySelector('#recipe').textContent; console.log('抓取到的菜谱内容:', recipeContent); } catch (err) { console.error('操作失败:', err); }
补充说明
如果按钮点击后菜谱内容是通过ajax请求后端接口获取的,你可以直接抓对应接口请求,跳过模拟DOM操作的步骤,直接构造接口参数请求获取数据,效率更高。
内容的提问来源于stack exchange,提问作者John Carter
相关产品推荐
相关产品推荐

