cheerio是jquery核心功能的一个快速灵活而又简洁的实现,主要是为了用在服务器端需要对DOM进行操作的地方

简介

cheerio是nodejs的抓取页面模块,为服务器特别定制的,快速、灵活、实施的jQuery核心实现。适合各种Web爬虫程序。

让你在服务器端和html愉快的玩耍

  1. var cheerio = require('cheerio'),
  2. $ = cheerio.load('<h2 class = "title">Hello world</h2>');
  3. $('h2.title').text('Hello there!');
  4. $('h2').addClass('welcome');
  5. $.html();

安装

  1. npm install cheerio

特点

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


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

关于JSDOM

jsdom是一个纯粹由 javascript 实现的一系列 web标准,特别是 WHATWG 组织制定的DOM和 HTML 标准,用于在 nodejs 中使用。大体上来说,该项目的目标是模拟足够的Web浏览器子集,以便用于测试和挖掘真实世界的Web应用程序。

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


API

给定一段HTML

  1. <ul id="fruits">
  2. <li class="apple">Apple</li>
  3. <li class="orange">Orange</li>
  4. <li class="pear">Pear</li>
  5. </ul>


1. 解析html(load)

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

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

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

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

或者把HTML字符串作为root

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

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

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

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

2. 选择器(selectors)

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

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


selectorcontext的范围内搜索,context的范围又包含在root的范围内。selectorcontext可以是一个字符串,DOM元素,DOM数组或者cheerio实例。root一般是一个HTML文档字符串
选择器是文档遍历和操作的起点。如同在jQuery中一样,它是选择元素节点最重要的方法,但是在jQuery中选择器建立在CSS选择器标准库上。cheerio的选择器实现了大部分的方法

  1. $('.apple', '#fruits').text()
  2. //=> Apple
  3. $('ul .pear').attr('class')
  4. //=> pear
  5. $('li[class=orange]').html()
  6. //=> <li class = "orange">Orange</li>


3. 属性操作(atrributes)

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

  1. $('ul').attr('id')
  2. //=> fruits
  3. $('.apple').attr('id', 'favorite').html()
  4. //=> <li class = "apple" id = "favorite">Apple</li>


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

.removeAtrr(name)
移除名为name的属性

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

.hasClass(className)
检查元素是否含有此类名

  1. $('.pear').hasClass('pear')
  2. //=> true
  3. $('apple').hasClass('fruit')
  4. //=> false
  5. $('li').hasClass('pear')
  6. //=> true

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

  1. $('.pear').addClass('fruit').html()
  2. //=> <li class = "pear fruit">Pear</li>
  3. $('.apple').addClass('fruit red').html()
  4. //=> <li class = "apple fruit red">Apple</li>


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

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

  1. $('.pear').removeClass('pear').html()
  2. //=> <li class = "">Pear</li>
  3. $('.apple').addClass('red').removeClass().html()
  4. //=> <li class = "">Apple</li>


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

遍历

.find(selector)
在当前元素集合中选择符合选择器规则的元素集合

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

.parent()
获取元素集合第一个元素的父元素

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

.next()
选择当前元素的下一个兄弟元素

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

.prev()
.next()相反
.siblings()
获取元素集合中第一个元素的所有兄弟元素,不包含它自己

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

.children( selector )
.each( function(index, element) )
遍历函数返回false即可终止遍历

  1. var fruits = [];
  2. $('li').each(function(i, elem) {
  3. fruits[i] = $(this).text();
  4. });
  5. fruits.join(', ');
  6. //=> Apple, Orange, Pear

.map( function(index, element) )

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

.filter( selector )

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

.filter( function(index) )

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

.first()

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

.last()

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

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

  1. $('li').eq(0).text()
  2. //=> Apple
  3. $('li').eq(-1).text()
  4. //=> Pear


操作DOM


操作DOM结构的方法
.append( content, [content, …] )
.prepend( content, [content, …] )
.after( content, [content, …] )**

  1. $('.apple').after('<li class = "plum">Plum</li>')
  2. $.html()
  3. //=> <ul id = "fruits">
  4. // <li class = "apple">Apple</li>
  5. // <li class = "plum">Plum</li>
  6. // <li class = "orange">Orange</li>
  7. // <li class = "pear">Pear</li>
  8. // </ul>

.before( content, [content, …] )

  1. $('.apple').before('<li class = "plum">Plum</li>')
  2. $.html()
  3. //=> <ul id = "fruits">
  4. // <li class = "plum">Plum</li>
  5. // <li class = "apple">Apple</li>
  6. // <li class = "orange">Orange</li>
  7. // <li class = "pear">Pear</li>
  8. // </ul>

.remove( [selector] )

  1. $('.pear').remove()
  2. $.html()
  3. //=> <ul id = "fruits">
  4. // <li class = "apple">Apple</li>
  5. // <li class = "orange">Orange</li>
  6. // </ul>

.replaceWith( content )

  1. var plum = $('<li class = "plum">Plum</li>')
  2. $('.pear').replaceWith(plum)
  3. $.html()
  4. //=> <ul id = "fruits">
  5. // <li class = "apple">Apple</li>
  6. // <li class = "orange">Orange</li>
  7. // <li class = "plum">Plum</li>
  8. // </ul>

.empty()

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

.html( [htmlString] )

  1. $('.orange').html()
  2. //=> Orange
  3. $('#fruits').html('<li class = "mango">Mango</li>').html()
  4. //=> <li class="mango">Mango</li>

.text( [textString] )

  1. $('.orange').text()
  2. //=> Orange
  3. $('ul').text()
  4. //=> Apple
  5. // Orange
  6. // Pear

解析和渲染

  1. $.html()
  2. //=> <ul id = "fruits">
  3. // <li class = "apple">Apple</li>
  4. // <li class = "orange">Orange</li>
  5. // <li class = "pear">Pear</li>
  6. // </ul>

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

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


常用工具

$.root()

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

$.contains( container, contained )


.toArray()

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

.clone()

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