简介
传统上,Node.js不允许你解析和操作标记,因为它在浏览器之外执行代码。在这篇文章中,我们将探讨Cheerio,一个专门为此目的设计的开源JavaScript库。
Cheerio提供了一个灵活而精简的jQuery实现,但它是为服务器设计的。用Cheerio操作和渲染标记是非常快的,因为它的工作方式是简洁的和简单的标记(类似于jQuery)。除了解析HTML之外,Cheerio还能很好地处理XML文档。
目标
本教程假设没有Cheerio的知识,并将涵盖以下方面。
- 在Node.js项目中安装Cheerio
- 了解Cheerio(加载、选择器、DOM操作和渲染)。
- 构建一个示例应用程序(FeatRocket),刮取LogRocket的特色文章并将其记录到控制台。
先决条件
要完成本教程,你将需要。
- 对HTML、CSS和DOM有基本的了解
- 熟悉npm和Node.js
- 熟悉命令行和文本编辑器的使用
设置Cheerio
Cheerio可用于任何ES6+、TypeScript和Node.js项目,但在本文中,我们将专注于Node.js。
为了开始,我们需要运行npm init -y 命令,它将生成一个新的package.json 文件,其内容如下。
{
"name": "cheerio-sample",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC"
}
一旦完成,让我们继续安装Cheerio。
npm install cheerio
验证安装是否成功的一个方法是检查 package.json 文件。你应该看到一个名为dependencies 的新条目,如下图。
...
"dependencies": {
"cheerio": "^1.0.0-rc.10"
}
了解Cheerio
装载
使用Cheerio的第一步是加载我们要解析或操作的HTML/XML文件。我们必须这样做,因为我们正在与Node.js一起工作,它不能直接访问我们的应用程序标记,除非是以某种方式下载。
加载可以通过cheerio.load() 方法实现,这需要一个重要的参数--你想要加载的HTML/XML文档。
下面是一个例子。
const cheerio = require("cheerio");
const markup = `<ul id="js-frameworks">
<li class="vue">Vue.js
与网页浏览器类似,使用cheerio.load() 方法将自动分别包括<html>,<head>, 和<body> 标签,如果它们还没有出现在我们的标记中。
你可以通过设置.load() 方法的第三个参数为false 来禁用这个功能。
const $ = cheerio.load(markup, null, false);
在你处理XML文档而不是HTML的情况下,这可能很方便。
选择器
我们使用选择器来告诉Cheerio我们想要处理什么元素。如前所述,Cheerio中选择器的实现类似于jQuery,它也遵循CSS风格,但有一些补充。
Cheerio中最常用的一些选择器包括。
$("*")- 星号(*)被用作通配符选择器,它将选择所提供的标记上的每个元素$("div")- 标签选择器:选择所提供的标签的每个实例。在这种情况下,它将选择<div>标签的每个实例。$(".foo")- 类:选择每个应用了foo类的元素。$("#bar")- Id:选择每一个具有唯一的barid的元素$(":focus")- 选择当前拥有焦点的元素$("input[type='text']")- 属性:选择任何输入类型为的输入元素。text$('.bar, '#foo)- 选择具有foo类的元素下的所有具有bar类的子元素
事件和DOM操作
与JQuery类似,Cheerio也有一堆DOM相关的方法,用于访问和操作HTML元素及其属性。
一些最常用的方法包括。
.text()- 设置或返回所选元素的innerText内容。以我们之前的标记为例,我们可以用下面的代码得到一个具有vue类别的元素的文本内容。$(".vue").text(); // output => Vue.js ⚡.html()- 设置或返回所选元素的innerHTML内容.append()- 将所提供的内容作为所选元素的_最后一个子_元素插入。.prepend()- 与append不同,这将插入所提供的内容作为每个选定元素的第一个孩子。.addClass()和.removeClass()- 将删除或添加所提供的类到所有匹配的元素中。.hasClass()- 如果所选元素有所提供的类名,返回一个布尔值(真/假)。.toggleClass()- 将检查所提供的类是否存在于所选元素中。如果存在,提供的类将被删除,否则它将被添加到所选元素的类列表中。
渲染
一旦你完成了对你的标记的解析和操作,你就可以访问它的根内容了。
$.root().html();
默认情况下,当你在Cheerio中解析HTML内容时,一些标签将被打开,而在你处理XML内容的情况下,XML文件将以这种方式无效。
为了渲染一个有效的XML文件,你可以使用Cheerio的XML实用功能。
// Loading XML content
const $ = cheerio.load(
'<media:thumbnail url="http://www.foo.com/keyframe.jpg" width="75" height="50" time="12:05:01.123"/>'
);
// Rendering xml content
$.xml();
// Output => <media:thumbnail url="http://www.foo.com/keyframe.jpg" width="75" height="50" time="12:05:01.123"/>
构建FeatRocket
现在我们对Cheerio的工作方式有了基本的了解,让我们继续构建一个示例项目。
我们将构建FeatRocket,这是一个CLI应用程序,它将抓取LogRocket博客上的所有特色文章,并将它们记录到我们的控制台。
以下是我们将如何实现这一目标。
- 了解LogRocket博客结构
- 下载网页标记
- 将下载的标记加载到一个新的Cheerio实例中
- 找到并过滤出需要的内容
- 将结果记录到控制台
了解网站结构
网页搜刮的第一步是了解网站的内容是如何安排的,也就是说,什么属性(class,id,href )是分配给你要访问的元素,等等。
在我们的案例中,我们可以注意到,我们的目标内容是像下面这样排列的。
<div class="listfeaturedtag">
<!-- first article -->
<div class="col.. padlr10"></div>
...
<!-- second article -->
<div class="col.. padlr10"></div>
...
</div>
其中div ,类别为listfeaturedtag ,是我们所有目标文章的包装,而divs,类别为col.. padlr10 ,是每个特色文章的卡片。
下载网页标记
我们现在明白了网站的结构和我们的目标内容。接下来创建一个新的文件scrapper.js ,然后继续安装Axios--我们将使用Axios来下载网站内容。
npm install axios
而我们可以用抓取网站源代码。
const axios = require("axios");
axios
.get("https://blog.logrocket.com/")
.then((response) => {
console.log(response)
})
.catch((err) => console.log("Fetch error " + err));
将上面的代码粘贴到新创建的scrapper.js 文件中,然后用这个运行。
node scrapper.js
你会发现,网站的整个HTML内容被记录到控制台。
将标记加载到Cheerio中
下一步是将下载的标记加载到一个新的Cheerio中。
const axios = require("axios");
const cheerio = require("cheerio");
axios
.get("https://blog.logrocket.com/")
.then((response) => {
const $ = cheerio.load(response.data);
})
.catch((err) => console.log("Fetch error " + err));
过滤出结果
接下来,我们想只过滤出需要的内容。我们已经知道我们的目标divs的属性(。listfeaturedtag 和.padlr10 )。我们只需要循环浏览每一个属性,并将它们记录到控制台,这样我们的完整代码就会是这样的。
const axios = require("axios");
const cheerio = require("cheerio");
axios
.get("https://blog.logrocket.com/")
.then((response) => {
const $ = cheerio.load(response.data);
const featuredArticles = $(".listfeaturedtag .padlr10");
for (let i = 0; i < featuredArticles.length; i++) {
let postTitleWrapper = $(featuredArticles[i]).find(".card-title")[0],
postTitle = $(postTitleWrapper).text();
let authorWrapper = $(featuredArticles[i]).find(".post-name a")[0],
author = $(authorWrapper).text();
let postDescWrapper = $(featuredArticles[i]).find(".card-text")[0],
postDesc = $(postDescWrapper).text();
let postLinkWrapper = $(featuredArticles[i]).find(".card-title > a")[0],
postLink = $(postLinkWrapper).attr("href");
// console.log("\n++++++");
console.log(`${postTitle} by [${author}]`);
console.log(`${postDesc}`);
console.log("\n" + `Read More - ${postLink}`);
console.log("\n----\n\n");
}
})
.catch((err) => console.log("Fetch error " + err));
现在,如果我们运行node scrapper.js ,你应该在控制台看到如下的输出。
结论
Cheerio是一个优秀的框架,用于在服务器端操作和爬取标记内容,而且它是轻量级的,实现了一个熟悉的语法。
本教程对如何在实际项目中开始使用Cheerio提供了一个深入的指导。
为了进一步参考,你也可以查看GitHub上的FeatRocket源代码。
谢谢你的阅读!
The postParsing HTML in Node.js with Cheerioappeared first onLogRocket Blog.