选择器解析 html 时的 Cheerio 问题

Cheerio problems on parsing html by selectors

    var request = require('request');
    var cheerio = require('cheerio');

    request('http://www.gatherproxy.com/proxylist/anonymity/?t=Elite', function (error, response, html) {
      if (!error && response.statusCode == 200) {
        var $ = cheerio.load(html);

        var temp = $('#tblproxy tbody tr.loading-row')

        console.log(temp.attr('class'))

      }
    });

网页位于http://www.gatherproxy.com/zh/proxylist/anonymity/?t=Elite

我想获取这个元素,它的选择器是#tblproxy > tbody > tr.loading-row

我在 google 控制台中尝试了同样的操作,

var s = $('#tblproxy > tbody > tr.loading-row')
undefined
s.attr('class')
"loading-row"

但它在 cheerio 的上下文中不起作用,程序的输出未定义,知道吗?

从页面的代码源来看,#tblproxy中没有tbody,所以从选择器中去掉:

var temp = $('#tblproxy tr.loading-row');

更新

根据bublik42的评论,如果随机出现tbody,可以使用find():

var temp = $('#tblproxy').find('tr.loading-row');

我注意到您尝试查询的元素 tbody 是异步加载的。这超出了 request 模块的能力范围。您可以使用 phantomjs in simulating a web page in a headless manner and get the html from a web page module. If you want to create more customized web page modules you can refer to the phantomjs documentation.

叉这个 github repo demo .

首先,创建一个网页模块来获取特定页面的html。

phantom/request.js

'use strict';

var page = require('webpage').create();
var system = require('system');

page.open(system.args[1], function(status) {

    console.log(page.evaluate(function() {
        return document.documentElement.innerHTML;
    }));

    phantom.exit();

});

其次,为 phantom 目录中的所有网页模块创建一个 phantomjs cli 包装器。

lib/phantom.js

'use strict';

var path = require('path');
var spawn = require('child_process').spawn;
var phantomjs = require('phantomjs');
var fs = require('fs');
var binPath = phantomjs.path;
var slice = Array.prototype.slice;

var phantomPath = path.join(
    __dirname,
    '..',
    'phantom'
);

exports = module.exports = function() {

    var args = slice.call(arguments);
    var callback = args.pop();

    var command = spawn(binPath, args);

    command.stdout.on('data', function(data) {
        callback(null, data.toString());
    });

    command.stderr.on('data', function(data) {
        callback({ message: data.toString() }, null);
    });

};

// create methods base on the ./phantom directory web page modules
fs.readdirSync(phantomPath).reduce(function(context, filename) {

    var index = path.basename(filename, '.js');

    context[index] = function() {
        exports.apply(null, [path.join(phantomPath, filename)].concat(slice.call(arguments)));
    };

}, exports);

最后,使用lib/phantom.js脚本的request方法获取html页面。

index.js

'use strict';

var phantom = require('./lib/phantom');
var cheerio = require('cheerio');

var address = 'http://www.gatherproxy.com/proxylist/anonymity/?t=Elite';

phantom.request(address, function(err, html) {

    if(err) {
        console.log('error');
        return;
    }

    var $ = cheerio.load(html);

    var temp = $('#tblproxy tbody tr.loading-row');

    console.log(temp.attr('class'));

});