cheerio 类似 jQuery 的服务器端 DOM 操作库

发布于 2020-04-21 23:13:09 字数 12972 浏览 2153 评论 0

这篇参考手册是对 cheerio 官方文档 的中文翻译,cheerio 是 jQuery 核心功能的一个快速灵活而又简洁的实现,主要是为了用在服务端需要对 DOM 进行操作的地方。

简介

让你在服务端和 HTML 愉快的玩耍:

var cheerio = require('cheerio'),
    $ = cheerio.load('<h2 class = "title">Hello world</h2>');

$('h2.title').text('Hello there!');
$('h2').addClass('welcome');

$.html();
//=> <h2 class = "title welcome">Hello there!</h2>

安装

npm install cheerio

特点

  • 熟悉的语法:cheerio 实现了 jQuery 的一个子集,去掉了 jQuery 中所有与 DOM 不一致或者是用来填浏览器的坑的东西,重现了 jQuery 最美妙的 API
  • 快到没朋友:cheerio 使用了及其简洁而又标准的 DOM 模型, 因此对文档的转换、操作、渲染都极其的高效。基本的端到端测试显示它的速度至少是 JSDOM 的 8 倍
  • 极其灵活:cheerio 使用了 @FB55 编写的非常兼容的 htmlparser2,因此它可以解析几乎所有的HTML和XML

关于 JSDOM

cheerio 产生的原因是出于对 JSDOM 的失望,主要体现在以下三点:

  • JSDOM的解析规则太过于严格:JSDOM 的解析器无法处理现在许多的流行网站的内容
  • JSDOM太慢了:解析大的网站甚至可以产生可察觉的延迟
  • JSDOM太过于重量级:JSDOM 的目标是提供与浏览器一样的 DOM 环境,但是我们往往不需要这样。我们需要的只是一种简单,熟悉的方式来操作我们的 HTML

什么时候你应该用JSDOM

cheerio 并非万能,当你需要一个浏览器一样的环境时,你最好还是用 JSDOM,尤其是你需要进行自动化的功能测试时

API

后面的例子中用到的HTML模板如下:

<ul id="fruits">
  <li class="apple">Apple</li>
  <li class="orange">Orange</li>
  <li class="pear">Pear</li>
</ul>

1. 解析html(load)

首先你需要先加载你的 HTML。jQuery 会自动完成这一步,因为 jQuery 操作的 DOM 是固定的。但是在使用 cheerio 时我们要手动加载我们的 HTML 文档

首选的方式如下:

var cheerio = require('cheerio'),
$ = cheerio.load('<ul id = "fruits">...</ul>');

其次,直接把HTML字符串作为上下文也是可以的:

$ = require('cheerio');
$('ul', '<ul id = "fruits">...</ul>');

或者把HTML字符串作为root

$ = require('cheerio');
$('li', 'ul', '<ul id = "fruits">...</ul>');

如果你需要自定义一些解析选项,你可以多传递一个对象给load方法:

$ = cheerio.load('<ul id = "fruits">...</ul>', {
    ignoreWhitespace: true,
    xmlMode: true
});

更多的解析选项可以参考domhandlerparser-options

2. 选择器(selectors)

cheerio的选择器几乎和jQuery一模一样,所以语法上十分相像

$( selector, [context], [root] )

selector context 的范围内搜索,context 的范围又包含在 root 的范围内。selector context 可以是一个字符串,DOM元素,DOM数组或者cheerio实例。root一般是一个HTML文档字符串

选择器是文档遍历和操作的起点。如同在jQuery中一样,它是选择元素节点最重要的方法,但是在jQuery中选择器建立在CSS选择器标准库上。cheerio的选择器实现了大部分的方法

$('.apple', '#fruits').text()
//=> Apple

$('ul .pear').attr('class')
//=> pear

$('li[class=orange]').html()
//=> <li class = "orange">Orange</li>

3. 属性操作(atrributes)

用来获取和更改属性的方法:

.attr(name, value)

这个方法用来获取和设置属性。获取第一个符合匹配的元素的属性值。如果某个属性值被设置成null,那么该属性会被移除。你也可以把mapfunction作为参数传递进去,就像在jQuery中一样

$('ul').attr('id')
//=> fruits

$('.apple').attr('id', 'favorite').html()
//=> <li class = "apple" id = "favorite">Apple</li>

更多信息请查看 http://api.jquery.com/attr/

.removeAtrr(name)

移除名为name的属性

$('.pear').removeAttr('class').html()
//=> <li>Pear</li>

.hasClass(className)

检查元素是否含有此类名

$('.pear').hasClass('pear')
//=> true

$('apple').hasClass('fruit')
//=> false

$('li').hasClass('pear')
//=> true

.addClass(className)

添加类名到所有的匹配元素,可以用函数作为参数

$('.pear').addClass('fruit').html()
//=> <li class = "pear fruit">Pear</li>

$('.apple').addClass('fruit red').html()
//=> <li class = "apple fruit red">Apple</li>

参见 http://api.jquery.com/addClass/

.remoteClass([className])

移除一个或者多个(空格分隔)的类名,如果className为空,则所有的类名都会被移除,可以传递函数作为参数

$('.pear').removeClass('pear').html()
//=> <li class = "">Pear</li>

$('.apple').addClass('red').removeClass().html()
//=> <li class = "">Apple</li>

参见 http://api.jquery.com/removeClass/

4. 遍历

.find(selector)

在当前元素集合中选择符合选择器规则的元素集合

$('#fruits').find('li').length
//=> 3

.parent()

获取元素集合第一个元素的父元素

$('.pear').parent().attr('id')
//=> fruits

.next()

选择当前元素的下一个兄弟元素

$('.apple').next().hasClass('orange')
//=> true

.prev()

.next()相反

.siblings()

获取元素集合中第一个元素的所有兄弟元素,不包含它自己

$('.pear').siblings().length
//=> 2

.children( selector )

.each( function(index, element) )

遍历函数返回false即可终止遍历

var fruits = [];

$('li').each(function(i, elem) {
  fruits[i] = $(this).text();
});

fruits.join(', ');
//=> Apple, Orange, Pear

.map( function(index, element) )

$('li').map(function(i, el) {
  // this === el
  return $(this).attr('class');
}).get().join(', ');
//=> apple, orange, pear

.filter( selector )

$('li').filter('.orange').attr('class');
//=> orange

.filter( function(index) )

$('li').filter(function(i, el) {
  // this === el
  return $(this).attr('class') === 'orange';
}).attr('class')
//=> orange

.first()

$('#fruits').children().first().text()
//=> Apple

.last()

$('#fruits').children().last().text()
//=> Pear

.eq( i )

缩小元素集合,可以用负数表示倒数第 i 个元素被保留

$('li').eq(0).text()
//=> Apple

$('li').eq(-1).text()
//=> Pear

5. 操作DOM

操作DOM结构的方法

.append( content, [content, ...] )

.prepend( content, [content, ...] )

.after( content, [content, ...] )

$('.apple').after('<li class = "plum">Plum</li>')
$.html()
//=>  <ul id = "fruits">
//      <li class = "apple">Apple</li>
//      <li class = "plum">Plum</li>
//      <li class = "orange">Orange</li>
//      <li class = "pear">Pear</li>
//    </ul>

.before( content, [content, ...] )

$('.apple').before('<li class = "plum">Plum</li>')
$.html()
//=>  <ul id = "fruits">
//      <li class = "plum">Plum</li>
//      <li class = "apple">Apple</li>
//      <li class = "orange">Orange</li>
//      <li class = "pear">Pear</li>
//    </ul>

.remove( [selector] )

$('.pear').remove()
$.html()
//=>  <ul id = "fruits">
//      <li class = "apple">Apple</li>
//      <li class = "orange">Orange</li>
//    </ul>

.replaceWith( content )

var plum = $('<li class = "plum">Plum</li>')
$('.pear').replaceWith(plum)
$.html()
//=> <ul id = "fruits">
//     <li class = "apple">Apple</li>
//     <li class = "orange">Orange</li>
//     <li class = "plum">Plum</li>
//   </ul>

.empty()

$('ul').empty()
$.html()
//=>  <ul id = "fruits"></ul>

.html( [htmlString] )

$('.orange').html()
//=> Orange

$('#fruits').html('<li class = "mango">Mango</li>').html()
//=> <li class="mango">Mango</li>

.text( [textString] )

$('.orange').text()
//=> Orange

$('ul').text()
//=>  Apple
//    Orange
//    Pear

6. 解析和渲染

$.html()
//=>  <ul id = "fruits">
//      <li class = "apple">Apple</li>
//      <li class = "orange">Orange</li>
//      <li class = "pear">Pear</li>
//    </ul>

输出包含自己在内的HTML(outer HTML)

$.html('.pear')
//=> <li class = "pear">Pear</li>

7. 杂项

.toArray()

$('li').toArray()
//=> [ {...}, {...}, {...} ]

.clone()

var moreFruit = $('#fruits').clone()

8. 常用工具

$.root()

$.root().append('<ul id="vegetables"></ul>').html();
//=> <ul id="fruits">...</ul><ul id="vegetables"></ul>

$.contains( container, contained )

Checks to see if the contained DOM element is a descendant of the container DOM element.

$.parseHTML( data [, context ] [, keepScripts ] )

Parses a string into an array of DOM nodes. The context argument has no meaning for Cheerio, but it is maintained for API compatibility.

$.load( html[, options ] )

Load in the HTML. (See the previous section titled “Loading” for more information.)

9. 插件

Once you have loaded a document, you may extend the prototype or the equivalent fn property with custom plugin methods:

const $ = cheerio.load('<html><body>Hello, <b>world</b>!</body></html>');
$.prototype.logHtml = function() {
  console.log(this.html());
};

$('body').logHtml(); // logs "Hello, <b>world</b>!" to the console

The “DOM Node” object

Cheerio collections are made up of objects that bear some resemblance to browser-based DOM nodes. You can expect them to define the following properties:

  • tagName
  • parentNode
  • previousSibling
  • nextSibling
  • nodeValue
  • firstChild
  • childNodes
  • lastChild

官网:https://cheerio.js.org/

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

JSmiles

生命进入颠沛而奔忙的本质状态,并将以不断告别和相遇的陈旧方式继续下去。

0 文章
0 评论
84961 人气
更多

推荐作者

娇女薄笑

文章 0 评论 0

biaggi

文章 0 评论 0

xiaolangfanhua

文章 0 评论 0

rivulet

文章 0 评论 0

我三岁

文章 0 评论 0

薆情海

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文