使用 Cheerio.js 在表中迭代 TR

Posted

技术标签:

【中文标题】使用 Cheerio.js 在表中迭代 TR【英文标题】:Iterating over TR in a table with Cheerio.js 【发布时间】:2015-04-07 20:49:36 【问题描述】:

我在使用我在 Node 服务器上使用的 Cheerio.js 可用的选择器时遇到问题。核心应该是基于 jQuery 的,但是我无法使用与原生 jQuery 相同的选择使其真正工作。

我有一个大致如下所示的 DOM:

<div class="test">
    <table class="listing">
        <thead><tr>few cells here</tr></thead>
        <tfoot></tfoot>
        <tbody><tr>These are the rows I want</tr></tbody>
    </table>
</div>

由于页面上有两个带有“listing”类的表,因此我无法直接选择它,因此我需要引用带有“test”类的 div。我可以使用 jQuery 运行的选择类似于:

$('div.test tbody tr')

但这不适用于 Cheerio。如果我运行 $('div[class="test"] tr') 我会得到桌子上的所有行,甚至是 thead 行,所以这对我不起作用。

有什么猜测吗?

更新: 这是我正在执行的实际代码(不起作用):

// Load the html
var $ = cheerio.load(html, 
    normalizeWhitespace: true
);

$('div.tillgodo tbody tr').each(function()
    console.log("Found credited course...");
    var children = $(this).children();
    var credits = parseFloat($(children[3]).text().replace(',', '.')); // We need to replace comma with a dot since parseFloats only supports dots by design

    var row = 
        "course" : $(children[1]).text().trim(),
        "grade" : null,
        "credits" : credits,
        "date" : $(children[4]).text()
    ;

    // Push course to JSON object
    console.log("Push course to object...");
    console.log("------------------------------------------\n");
    data.credited_courses.push(row);
    data.credited_courses_credits += parseFloat(credits);
);

以下代码适用于 first 表:

$('tr.incomplete.course').each(function(i, tr)
    console.log("This is course nr: " + parseInt(course_count+1));
    console.log("Found incompleted course...");
    var children = $(this).children();
    var credits = parseFloat($(children[2]).text().replace(',', '.').match(/(\+|-)?((\d+(\.\d+)?)|(\.\d+))/)[0]); // Filter out any parentheses and odd characters
    var row = 
        "course" : $(children[1]).text(),
        "grade" : $(children[3]).text(),
        "credits" : credits,
        "date" : $(children[5]).text()
    ;

    // Sum the total amount of credits for all courses
    console.log("Add credits to incompleted_credits...");
    data.incompleted_credits += credits;

    console.log("Push course to object...");
    data.incompleted_courses.push(row);
    course_count++;
);

当我说它不起作用时,意味着我返回的 JSON 对象没有第二个表中的预期行。

更新 2 我要刮的表:

<div class="tillgodo">
    <h2>Tillgodoräknanden</h2>
    <table class="listing">
    <thead>
    <tr class="listingHeader">
        <th>Kurskod</th>
        <th>Kursnamn</th>
        <th>Beslutsfattare</th>
        <th class="credits">Poäng</th>
        <th>Datum</th>
    </tr>
    </thead>
    <tfoot>
    <tr class="listingTrailer">
        <td>
        </td><td colspan="2">Summa tillgodoräknade poäng:
        </td><td class="credits">10,5
        </td><td>
    </td></tr>
    </tfoot>

        <tbody><tr>
            <td>
            </td><td>Valfria kurser
            </td><td>xxx
            </td><td class="credits">10,5
            </td><td class="nobreak">2013-06-03
        </td></tr>

    </tbody>
</table>
</div>

最终更新(问题已解决) 我一直使用的选择器正在工作。但是源 HTML 格式错误,根本没有 tbody 标记。浏览器(在我的例子中是 Chrome)修复了问题,但很难找到真正的问题。

【问题讨论】:

请发布您的代码。我加载了您的 HTML 并使用您正在使用的选择器迭代了 tr 元素。我怀疑你的选择器没问题,但你没有在你的 javascript 中正确使用cheerio API。 好的,没问题。用实际代码更新了问题。 我认为这是您应该创建Minimal, Complete, Verifiable Example 的情况。在像这样抓取代码时,关于 HTML、选择器和 javascript 的所有内容都必须对齐。细节决定成败。您的代码看起来很脆弱,但如果没有 MCVE,除了“不要犯任何错误”之外,我们无能为力。 我知道这很难提供帮助。作为最后的手段,我可​​以为我想要抓取的表格提供 HTML :) 检查您的cheerio 版本?当我运行您的代码时,我得到一个“Valfria kurser”行,根据您的 sn-ps,这似乎是正确的。我正在使用cheerio 0.18.0。 【参考方案1】:

只是想像您所说的那样清楚地添加,如果选择器无法按预期工作,首先要做的是验证您的 html 是否有效。

你的 html 有效吗?

https://validator.w3.org/#validate_by_input

https://jsonformatter.org/html-validator

【讨论】:

【参考方案2】:

你可以试试$(div.test table.listing tr).text()

这将为您提供该表中所有 tr 标记的文本

【讨论】:

我如何使用id 做到这一点?

以上是关于使用 Cheerio.js 在表中迭代 TR的主要内容,如果未能解决你的问题,请参考以下文章

Thymeleaf 在表中为 <tr> 使用局部变量

在 Node/Express 中使用 Request.js 和 Cheerio.js 返回空数组

使用 select 语句在表中插入

替换cheerio选择器中的每个节点

如何使用 sql Bulkcopy 在表中插入 datagridview 行

记录未使用 PLSQL 过程保存在表中