【问题标题】:Cheerio direct child selectorCheerio 直接子选择器
【发布时间】:2016-08-11 03:12:36
【问题描述】:

大家好,女士们,首先这是我在 stackoverflow 中的第一个问题,所以不要对我这么苛刻.. 但是 w/e :P。 我有个问题.. 我对网络抓取完全陌生,目前我遇到的问题是我无法选择正确的元素。我的代码如下所示:

var express = require('express');
var path = require('path');
var request = require('request');
var cheerio = require('cheerio');
var fs = require('fs');

var app = express();
var port = 8000;

var url = "http://www.finanzparasiten.de/html/links/awd.html";

request(url, function (err, resp, body) {
    if(!err) {
        var $ = cheerio.load(body)

        var test = $('body table table table > tbody > tr > td > p');
        console.log(test.html())   
        test.each(function (ii, asdf) {
            var rr = $(asdf).find("table").find("tr").first().find('td:nth-child(2)').text();
            console.log(asdf);
        }) 
    } else {
        console.log("we encountered an error: " + err);
    }
});

app.listen(port);
console.log('server is listening on ' + port);

它不断为变量 test 记录 NULL。 似乎cheerio 的 > 选择器有问题。使用 jQuery,此选择将​​按预期工作。

感谢@logol 的anwser,我可以解决第一个问题,但现在我面临的问题是我必须在 body 之后选择直接子代,并且它似乎是错误的 tbody.. any1 有解决方法吗?

【问题讨论】:

    标签: javascript jquery web-scraping request cheerio


    【解决方案1】:

    原文:

    据我记得(当我上次使用cheerio 时)tbody 在cheerio 中不被识别,留下它并使用它来代替:

    表格 > tr > td

    PS:thead 工作正常

    更新:

    它似乎有时甚至可以使用 tbody,在 REPL 中试试这个

    const cheerio = require('cheerio');
    const html = '\
    <!DOCTYPE html>\
    <html>\
      <head>\
        <title>Cheerio Test</title>\
      </head>\
      <body>\
        <div id="#1">\
          <table>\
            <thead>\
              <tr>\
                <th>Month</th>\
                <th>Savings</th>\
              </tr>\
            </thead>\
            <tfoot>\
              <tr>\
                <td>Sum</td>\
                <td>180</td>\
              </tr>\
            </tfoot>\
            <tbody>\
              <tr>\
                <td>January</td>\
                <td>100</td>\
              </tr>\
              <tr>\
                <td>February</td>\
                <td>80</td>\
              </tr>\
            </tbody>\
          </table>\
        </div>\
      </body>\
    </html>';
    const dom = cheerio.load(html);
    
    // not working:
    let tds1 = dom('div#1 > table > tbody > tr > td').map(function () {
      return dom(this).text().trim();
    }).get();
    
    // working:
    let tds2 = dom('table > tbody > tr > td').map(function () {
      return dom(this).text().trim();
    }).get();
    
    // not working:
    let tds3 = dom('div#1 > table > tr > td').map(function () {
      return dom(this).text().trim();
    }).get();
    
    console.log(tds1);
    console.log(tds2);
    console.log(tds3);
    

    【讨论】:

    • 哇,这似乎有效:哦,谢谢你,身体也可能无法识别吗?例如body > div:last-of-type 似乎也失败了
    • 我玩了一会儿,有时它工作有时不.. 见 user3366016 更深入的调查
    • 如果我有多个表并且我事先不知道它们的顺序,只知道它们应该有什么内容怎么办?在我的情况下,这太硬编码而无法访问特定表。特别是如果桌子里面有桌子。
    【解决方案2】:

    更新:

    根据@logol 的回复,我检查了docs for Cheerio,它说它的选择器是基于CSSSelect 库构建的。他们的docs 有一个选择器列表。支持子选择器和父选择器,这似乎暗示所有元素选择器也是如此。但是,这个 github issue 标记了 tbody 问题。

    原文:

    你的意思是在你的选择器中列出重复的表,以及你如何在控制台中打印出来。

    试试这个:

    var test = $('body table > tbody > tr > td > p');
    console.log(test.innerHTML)
    

    这个在网页上的输出是:

    <span class="TDheadlinebig">AWD - Allgemeiner
                    Wirtschaftsdienst</span><span class="TDnormal"><br>
                    </span><span class="TDheadlinenormal">zweitgrößte "Strukkibude"
                    </span><span class="TDnormal"><br>
                    </span>
    

    【讨论】:

    • 感谢您的回复,但这不是问题,如果您愿意,您可以检查网址。每次直接选择都会发生在我身上。也许这是一个糟糕的选择,但当我使用你的选择时它也是 NULL。
    • 用 jquery 是的。但正如我提到的,我使用cheerio 进行网络抓取
    • @logol 是在做某事 :) 我不是;但我添加了一些文档和一个 github 问题与相同的 tbody 问题。
    • 是的完美 :) 但似乎我也发生了 body any1 有一种解决方法可以直接选择 body 之后的子项,例如 $("body > div:not(:first-of-type)") ;我需要选择直接的 div 并且不可能选择除了 body 作为父级以外的其他东西......
    • 无法对此进行测试,但可能想尝试加载正文,然后找到 div 并获得第一个。 $('body').find('div').first()github PR
    猜你喜欢
    • 2021-09-25
    • 2015-12-18
    • 2011-12-27
    • 1970-01-01
    • 2019-08-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-17
    相关资源
    最近更新 更多