Cheerio 在通过选择器解析 html 时出现问题

Cheerio problems on parsing html by selectors

本文关键字:html 问题 选择器 Cheerio      更新时间:2023-09-26
    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.load-row

我在谷歌控制台中尝试了同样的事情,

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

但它在 cheerio 的上下文中不起作用,程序的输出是未定义的,有什么想法吗?

我注意到您尝试查询的元素 tbody 是异步加载的。这超出了request模块的功能范围。您可以使用 phantomjs 以无头方式模拟网页,并从网页模块中获取 html。如果要创建更多自定义的网页模块,可以参考phantomjs documentation

分叉这个 github 存储库演示 .

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

幻影/请求.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 包装器。

库/幻影.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 页面。

索引.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'));
});

从页面的代码源中,#tblproxy 中没有tbody,因此请将其从选择器中删除:

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

更新

按照 bublik42 的评论,如果随机出现tbody,您可以使用find()

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