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

Node.js爬虫报错:无法读取null的innerText属性求助

问题排查与修复方案

报错原因

TypeError: Cannot read properties of null (reading 'innerText') 说明代码中 document.querySelector 未找到目标元素,返回了null,后续读取innerText时触发错误。核心原因有两个:

  1. 页面结构变更:你使用的冗长硬编码选择器(比如#main-content > div > section:nth-child(3) > div.css-gg4vpm...)依赖动态生成的CSS类名(如css-gg4vpm)和固定层级(如nth-child(3)),这类内容极易在网站更新时失效。
  2. 元素未完全加载:仅等待Cookie按钮不足以确保目标价格元素完成动态渲染,提前执行获取操作会导致找不到元素。

修复步骤

1. 替换为稳定的语义化选择器

放弃依赖动态类名和层级,改用文本内容定位元素(StockX的买卖按钮文本不会轻易变更):
修改pageScraper.js中的page.evaluate部分:

const result = await page.evaluate(() => {
    let demandes = '';
    let offres = '';
    // 遍历所有按钮,通过文本匹配目标元素
    const allButtons = document.querySelectorAll('a.chakra-button, button.chakra-button');
    allButtons.forEach(btn => {
        const pTag = btn.querySelector('p');
        if (pTag && pTag.innerText.includes('Acheter')) {
            demandes = pTag.innerText;
        } else if (pTag && pTag.innerText.includes('Vendre')) {
            offres = pTag.innerText;
        }
    });
    return { demandes, offres };
})

2. 添加元素加载等待逻辑

在执行元素获取前,确保目标内容已渲染完成:

// 在点击Cookie按钮后添加
await page.waitForFunction(() => {
    // 等待包含"Acheter"和"Vendre"的文本元素出现
    return document.querySelector('p:contains("Acheter")') && document.querySelector('p:contains("Vendre")');
}, { timeout: 10000 }); // 超时时间设为10秒,避免无限等待

3. 完善错误处理与资源释放

避免单个元素找不到导致爬虫崩溃,同时规范浏览器资源关闭:
修改scraper函数:

async scraper(browser){
    let page;
    try {
        page = await browser.newPage();
        console.log(`Navigating to ${this.url}...`);
        // 等待网络空闲,确保页面静态资源加载完成
        await page.goto(this.url, { waitUntil: 'networkidle2' });

        await page.waitForSelector('#onetrust-reject-all-handler', { timeout: 5000 });
        await page.click('#onetrust-reject-all-handler');

        // 等待目标元素加载
        await page.waitForFunction(() => {
            return document.querySelector('p:contains("Acheter")') && document.querySelector('p:contains("Vendre")');
        }, { timeout: 10000 });

        const result = await page.evaluate(() => {
            let demandes = '';
            let offres = '';
            const allButtons = document.querySelectorAll('a.chakra-button, button.chakra-button');
            allButtons.forEach(btn => {
                const pTag = btn.querySelector('p');
                if (pTag && pTag.innerText.includes('Acheter')) {
                    demandes = pTag.innerText;
                } else if (pTag && pTag.innerText.includes('Vendre')) {
                    offres = pTag.innerText;
                }
            });
            return { demandes, offres };
        })
        console.log(result);
        return result;
    } catch (err) {
        console.error('爬虫执行出错:', err);
        return { demandes: null, offres: null };
    } finally {
        // 先关闭页面再关闭浏览器,避免资源泄漏
        if (page) await page.close();
        if (browser) await browser.close();
    }
}

4. 优化文件写入逻辑

改用Promise风格的文件写入,和async/await语法统一:
修改pageController.js中的写入部分:

const scrapedData = await pageScraper.scraper(browser)
try {
    // 格式化JSON输出,更易读
    await fs.promises.writeFile("data.json", JSON.stringify(scrapedData, null, 2), 'utf8');
    console.log("数据已抓取并保存成功!可查看 './data.json'");
} catch (err) {
    console.error('写入文件出错:', err);
}

总结

核心问题是依赖不稳定的动态选择器且缺少元素加载等待。改用基于文本的语义化选择器,添加等待和错误处理后,爬虫会更健壮,能应对网站的小幅度更新。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 14:45:40