You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NextJs中使用Puppeteer爬取时遭遇执行上下文销毁错误的求助

解决Puppeteer导航导致执行上下文销毁的问题并实现全站搜索爬取逻辑

错误原因分析

你遇到的Error: Execution context was destroyed, most likely because of a navigation.是因为触发搜索后页面发生跳转,原页面的执行上下文被销毁,但代码未正确等待导航完成就继续操作,导致后续调用失效。

核心修复与优化点

  1. 循环处理歌曲列表:替换硬编码的歌曲名,遍历传入的songs数组逐个处理
  2. 等待导航完成:触发搜索和点击结果后,用waitForNavigation等待页面加载完成,避免操作已失效的上下文
  3. 修正元素交互逻辑:用click()替代press('Enter')触发搜索和点击结果,更符合页面正常交互流程
  4. 修复DOM选择器错误:document.querySelectorAll的参数应为逗号分隔的选择器字符串,而非多个独立参数
  5. 优化数据提取逻辑:精准定位目标元素,减少无效DOM遍历

修正后的代码

urlScrapper.js

import InfringementFinder from './InfringementFinder.js';

const songs = ['Artist Name - Song Name', 'Artist Name - Song Name'];
const irscCodes = ['XXXXXXXXXX', 'XXXXXXXXXX']; // 修正:字符串需添加引号

InfringementFinder(songs, irscCodes).then(() => {
  console.log('Search complete!');
}).catch((error) => {
  console.error(error);
});

InfringementFinder.js

import puppeteer from 'puppeteer';

const InfringementFinder = async (songs, irscCodes) => {
  const browser = await puppeteer.launch({ headless: false }); // 开启可视化模式方便调试
  const page = await browser.newPage();
  const mainPage = 'https://example.com/';

  try {
    await page.goto(mainPage, { waitUntil: 'networkidle2' }); // 等待页面资源加载完成

    // 遍历每首歌曲执行搜索爬取
    for (const [index, song] of songs.entries()) {
      const irscCode = irscCodes[index];
      console.log(`正在搜索:${song}`);

      // 清空搜索框并输入当前歌曲名
      await page.$eval('.search-field', el => el.value = '');
      await page.type('.search-field', song, { delay: 100 }); // 模拟真实输入速度,降低被拦截风险

      // 触发搜索并等待结果页面加载完成
      await Promise.all([
        page.waitForNavigation({ waitUntil: 'networkidle2' }),
        page.click('.search-submit')
      ]);

      // 等待搜索结果元素出现,超时则跳过当前歌曲
      const entryContent = await page.waitForSelector('.g1-frame', { timeout: 5000 }).catch(() => null);
      if (!entryContent) {
        console.log(`未找到歌曲${song}的搜索结果`);
        continue;
      }

      // 点击搜索结果并等待详情页加载完成
      await Promise.all([
        page.waitForNavigation({ waitUntil: 'networkidle2' }),
        entryContent.click()
      ]);

      // 提取歌曲信息与下载链接
      const data = await page.evaluate((targetSong, targetIrsc) => {
        // 定位包含目标歌曲名的元素
        const trackElement = document.querySelector(`*:contains("${targetSong}")`);
        const trackName = trackElement ? trackElement.innerText.trim() : '未知歌曲名';
        
        // 提取有效下载链接
        const downloadLinks = Array.from(document.querySelectorAll('.dl-btn'))
          .map(link => link.getAttribute('href'))
          .filter(href => href);

        return {
          songName: targetSong,
          irscCode: targetIrsc,
          trackName,
          downloadLinks
        };
      }, song, irscCode); // 将外部变量作为参数传入evaluate,避免上下文隔离问题

      console.log(`歌曲${song}爬取结果:`, data);
      // 可在此添加数据保存(文件/数据库)逻辑
    }
  } catch (error) {
    console.error('爬取过程出错:', error);
  } finally {
    await browser.close();
  }
};

export default InfringementFinder;

额外提示

  • 调试阶段保持headless: false,可直观查看页面操作流程
  • waitUntil: 'networkidle2'确保页面资源加载稳定后再执行下一步,减少因页面未加载完成导致的错误
  • 用Promise.all同时触发操作和等待导航,避免竞态条件

内容的提问来源于stack exchange,提问作者kelvin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 03:20:52