如何使用节点逐个获取元素.js Cheerio

How to get element one by one using node.js Cheerio

本文关键字:元素 js Cheerio 获取 何使用 节点      更新时间:2023-09-26

我正在使用Cheerio,Request在Node.js制作网络爬虫。我用了一些刮刀,但我不知道jQuery熟悉的刮刀,Cheerio。无论如何,让我们看看问题所在。

.html

<li><a title="FR" class="A">176.31.239.33:8133</a></li>
<li><a title="FR" class="B">87.98.218.86:3128</a></li>
<li><a title="CN" class="A">183.62.60.100:80</a></li>
<li><a title="CN" class="A">183.131.152.227:80</a></li>
<li><a title="CN" class="A">183.238.133.43:80</a></li>

我想选择具有class="A"的元素,然后其文本(183.62.60.100:80).然后制作数组。

[ 
{ 'title' : 'FR', 'IP' : '176.31.239.33:8133' }, 
{ 'title' : 'CN', 'IP' : '183.62.60.100:80' },
...
]

但我被卡住了。我试过了。。。

var $ = cheerio.load(html);
var arr = $('a[class=A]').text();
console.log(arr) 
// result is 
// 176.31.239.33:8133183.62.60.100:80183.131.152.227.80
// if I print console.log(arr[0]), the result is just 1

重用不是数组,所以我无法一一拾取。我该怎么做?

您应该循环访问jquery/cherrio选择器返回的集合,并获取每个元素的 title 属性及其内部文本。尝试:

var $ = cheerio.load(html);
var arr = $('a[class=A]');   
var array = [];
arr.each(function() {
    array.push({
        title: $(this).attr('title'),
        IP: $(this).text()
    });
});

您也可以尝试将表达式替换为$("a.A") $('a[class=A]') 。它看起来更干净。

Cheerio遵循jQuery首先对集合进行操作的风格,如果这是像.text()这样的聚合器函数被调用的风格。如果要单独显示每个元素的文本,请对其进行迭代或映射。

这是现有答案的替代方案:

const cheerio = require("cheerio"); // 1.0.0-rc.12
const html = `
<li><a title="FR" class="A">176.31.239.33:8133</a></li>
<li><a title="FR" class="B">87.98.218.86:3128</a></li>
<li><a title="CN" class="A">183.62.60.100:80</a></li>
<li><a title="CN" class="A">183.131.152.227:80</a></li>
<li><a title="CN" class="A">183.238.133.43:80</a></li>
`;
const $ = cheerio.load(html);
const data = [...$("a.A")].map(e => ({
  title: $(e).attr("title"),
  IP: $(e).text(),
}));
console.log(data);

也可以使用 jQuery 样式的映射器并.get().toArray()返回本机数组:

const data = $("a.A")
  .map((i, e) => ({
    title: $(e).attr("title"),
    IP: $(e).text(),
  }))
  .toArray();

请注意,map的参数(index, element)在jQuery中,而不是与本机JS map (element, index)

喜欢这个的理由:

  • map是常见迭代习语的专业化:

    const result = [];
    array.forEach(e => {
       result.push(transform(e));
    });
    return result;
    

    哪个更干净,更容易写成:

    const result = array.map(transform);
    
  • 选择器"a.A"通常优于'a[class="A"]',因为[class="A"]非常具体。如果添加另一个类,它将失败。与map一样,它更容易编写和阅读。