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

如何在Nightmare.js中传递evaluate返回变量实现多页表格提取

问题诊断

你遇到的核心问题是Nightmare.js的evaluate()运行在独立的浏览器上下文,无法直接访问Node.js环境的变量,同时你在generator函数中没有正确保存和传递上一次evaluate()返回的结果。另外代码里还有几个细节问题需要修正:

  • 第一次evaluate()只返回了totalPageNumber,但没返回第一页的表格HTML,导致后续没有初始值可拼接;
  • CSS选择器里的>是HTML转义字符,在JS字符串中应该直接用>;
  • 循环硬编码了i <= 11,应该用实际获取的总页数;
  • 传递参数给evaluate()时,没有正确接收返回值并更新变量。

修正后的完整代码

function *run() {
    let nightmare = Nightmare({ show: true });
    // 登录并跳转到目标页面
    yield nightmare
        .goto('https://www.svgame168.com/IGKiosk/guest/login.aspx')
        .select('#ctl00_ddlLanguage', 'th-TH')
        .wait(3000)
        .insert('input[name="ctl00$ContentPlaceHolder1$Login1$UserName"]', userName)
        .insert('input[name="ctl00$ContentPlaceHolder1$Login1$Password"]', password)
        .click('#ctl00_ContentPlaceHolder1_Login1_LoginButton')
        .wait(3000)
        .goto('https://www.svgame168.com/IGKiosk/playermgt/Default.aspx')
        .click('#ctl00_ContentPlaceHolder1_searchBtn')
        .wait(6000);

    // 第一次获取:总页数 + 第一页表格HTML
    let initialData = yield nightmare.evaluate(function () {
        const nextPageExist = document.evaluate("//a[contains(., '>')]", document, null, XPathResult.ANY_TYPE, null).iterateNext();
        const tableHtml = document.querySelector("#ctl00_ContentPlaceHolder1_dataGridView").outerHTML;
        // 修正CSS选择器里的转义字符
        const totalPageEl = document.querySelector("#main_content_table > tbody > tr > td > table:nth-child(5) > tbody > tr > td > table > tbody > tr > td > div:nth-child(4) > span > div:nth-child(1)");
        const totalPageNumber = totalPageEl ? parseInt(totalPageEl.textContent.replace(/\D/g, ''), 10) : 1;
        
        if (nextPageExist) {
            nextPageExist.className += " nextPageExist1";
        }
        return { totalPageNumber, tableHtml };
    });

    let result = initialData.tableHtml;
    const totalPages = initialData.totalPageNumber;

    // 循环处理剩余页面
    for (let i = 2; i <= totalPages; i++) {
        console.log("Currently on page " + i);
        yield nightmare.click(".nextPageExist" + (i - 1)).wait(6000);
        
        // 传递当前result到浏览器上下文,拼接新页面的表格HTML
        result = yield nightmare.evaluate(function (currentResult) {
            const nextPageExist = document.evaluate("//a[text()='>']", document, null, XPathResult.ANY_TYPE, null).iterateNext();
            const newTableHtml = document.querySelector("#ctl00_ContentPlaceHolder1_dataGridView").outerHTML;
            const updatedResult = currentResult + newTableHtml;

            if (nextPageExist) {
                // 修正CSS选择器
                const pageNumberEl = document.querySelector("#main_content_table > tbody > tr > td > table:nth-child(5) > tbody > tr > td > table > tbody > tr > td > div:nth-child(4) > span > div:nth-child(2) > span");
                const pageNumber = pageNumberEl ? pageNumberEl.textContent.replace(/\D/g, '') : i;
                nextPageExist.className += " nextPageExist" + pageNumber;
            }
            return updatedResult;
        }, result); // 这里把Node环境的result传递给浏览器上下文的evaluate函数
    }

    // 关闭Nightmare并处理结果
    yield nightmare.end();
    try {
        console.log(tabletojson.convert(result));
    } catch (error) {
        console.error('Conversion failed:', error);
    }
}

关键修正点解释

  1. 分离初始数据获取:第一次evaluate()返回包含总页数和第一页HTML的对象,确保有拼接的初始值;
  2. 正确传递参数:在evaluate()函数后添加result参数,Nightmare会自动把Node环境的变量序列化后传入浏览器上下文,函数内部通过currentResult接收;
  3. 持续更新结果:循环中每次yieldevaluate()后,把返回的新HTML字符串赋值给result,实现页面内容的累加;
  4. 修正选择器问题:把CSS和XPath中的&gt;换成实际的>,JS字符串不需要HTML转义;
  5. 动态适配页数:用实际获取的totalPageNumber代替硬编码的11,适配不同数据量;
  6. 优化错误处理:把结果转换逻辑放在generator内部,避免then链的嵌套问题。

额外提示

  • 尽量减少固定时间的wait(),换成wait(selector)等待目标元素加载完成(比如wait("#ctl00_ContentPlaceHolder1_dataGridView")),这样更可靠;
  • 如果表格结构复杂,tabletojson可能需要配置参数来正确解析,建议先打印result确认HTML结构是否完整。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 13:47:31