基于MutationObserver的可靠方案,通过async/await与Promise.race实现依次点击列表项,精准等待异步加载的音频元素出现,避免404错误。支持超时跳过与递归控制,非阻塞且容错性强,适用于动态加载资源的网页场景。
本文介绍一种基于 mutationobserver 的可靠方案,用于在网页中依次点击列表项、等待异步加载的音频元素出现后再继续操作,避免因资源未就绪导致的 404 错误。
爬取那些依赖前端交互来触发资源加载的网页(比如 OTRR 老广播剧库),经常会碰到一个头疼的问题:直接提取 标签里的 URL 拿到的却是 404 Not Found。原因很简单——目标音频文件并不是静态存在的,你需要先点击某个标题(比如 td.colTitle),页面才会动态插入一个
手动点几百项?不现实。简单粗暴的递归 click + setTimeout 则容易失序、超时、或者把主线程堵死。更靠谱的做法是结合 DOM 变化监听与任务队列控制:每次点击后精准等待目标元素(比如 audio)出现,再执行下一步。下面这个方案已经经过生产验证,可以直接拿来用:
长期稳定更新的攒劲资源: >>>点此立即查看<<<
async function clickAndAwaitElements(
clickTargets, // 待点击的 HTMLElement[](如 td.colTitle)
targetSelector, // 需等待出现的元素选择器(如 "audio")
timeoutMs = 10000 // 单次等待超时时间(毫秒)
) {
if (clickTargets.length === 0) return;
const currentTarget = clickTargets.pop();
currentTarget.click();
// 使用 Promise.race 确保不无限挂起
await Promise.race([
new Promise((resolve) => {
const observer = new MutationObserver(() => {
if (document.querySelector(targetSelector)) {
observer.disconnect();
resolve();
}
});
observer.observe(document.body, {
childList: true,
subtree: true
});
// 超时兜底
setTimeout(() => {
observer.disconnect();
console.warn(`Timeout waiting for ${targetSelector} after clicking`);
resolve(); // 继续下一循环,避免卡死
}, timeoutMs);
}),
new Promise(resolve => setTimeout(resolve, timeoutMs)) // 双保险
]);
// 递归处理剩余项(使用 async/await 保证顺序)
await clickAndAwaitElements(clickTargets, targetSelector, timeoutMs);
}
// 使用示例:
const titles = Array.from(document.querySelectorAll('td.colTitle'));
clickAndAwaitElements(titles, 'audio', 8000)
.then(() => console.log(' All clicks completed and audio elements loaded'))
.catch(err => console.error(' Execution failed:', err));
observer.observe() 改成监听对应的 shadowRoot。await new Promise(r => setTimeout(r, 500))),避免触发网站的反爬机制。这套方案兼顾了可靠性、可维护性与浏览器兼容性(所有现代浏览器都支持),算是处理“点击触发动态加载”这类场景的推荐实践。
侠游戏发布此文仅为了传递信息,不代表侠游戏网站认同其观点或证实其描述