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

使用Puppeteer爬取YouTube搜索视频遇异常:终端返回undefined

Puppeteer爬取YouTube搜索结果返回undefined的问题解决

核心问题:DOM对象无法跨上下文序列化

Puppeteer的page.evaluate()运行在浏览器上下文,返回值必须是能被JSON序列化的数据才能传递到Node.js环境。document.querySelectorAll()返回的NodeList是DOM集合对象,包含浏览器内部的不可序列化引用,直接返回会变成undefined。而浏览器控制台能正常输出,是因为它本身就在浏览器上下文里,不需要跨环境传递数据。

其他代码问题

  1. URL拼接语法错误:breakSearchTermDownForYoutubeUrl函数里的replace(/ /g, "+"))多了一个右括号,会导致URL生成失败。
  2. 浏览器实例泄漏:原代码每次调用getPageToScrape都会新建浏览器实例,但没有关闭逻辑,长期运行会占用大量系统资源。
  3. 页面加载判断不准确:networkidle0仅表示网络空闲,但YouTube搜索结果是动态渲染的,此时DOM可能还未生成目标元素。

修正后的代码

import puppeteer from "puppeteer";

// 修复URL拼接的语法错误
const breakSearchTermDownForYoutubeUrl = (term) => {
    return `https://youtube.com/results?search_query=${term.replace(/ /g, "+")}`;
};

// 优化浏览器实例管理,避免重复创建与资源泄漏
const scapeYoutubeLink = async (term) => {
    const browser = await puppeteer.launch({
        headless: false,
        defaultViewport: null,
    });

    try {
        const page = await browser.newPage();
        const url = breakSearchTermDownForYoutubeUrl(term);
        
        await page.goto(url, {
            waitUntil: 'networkidle2', // 更适配动态渲染页面的网络等待策略
        });

        // 等待目标视频元素加载完成(使用YouTube搜索结果的标准视频容器选择器)
        await page.waitForSelector("ytd-video-renderer", { timeout: 10000 });

        const videos = await page.evaluate(() => {
            // 将NodeList转为普通数组,提取可序列化的视频信息
            return Array.from(document.querySelectorAll("ytd-video-renderer")).map(video => {
                const titleElement = video.querySelector("#video-title");
                return {
                    title: titleElement?.textContent.trim(),
                    link: `https://youtube.com${titleElement?.getAttribute("href")}`
                };
            });
        });

        console.log("爬取到的视频信息:", videos);
    } catch (error) {
        console.error("爬取出错:", error);
    } finally {
        // 确保浏览器实例被关闭,释放资源
        await browser.close();
    }
};

// 启动爬取
scapeYoutubeLink("acevane");

关键修改说明

  • 序列化处理:用Array.from()将NodeList转为普通数组,再提取标题、链接等可序列化的文本数据,避免直接返回DOM对象。
  • 等待元素加载:通过page.waitForSelector()等待YouTube的视频渲染元素ytd-video-renderer出现,确保DOM已完全生成目标内容。
  • 资源管理:将浏览器实例的创建与关闭放在try/finally块中,保证无论爬取成功或失败,都会关闭浏览器,避免资源泄漏。
  • 语法修复:移除URL拼接逻辑中多余的右括号,确保生成的搜索URL合法。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 09:40:12