Node.js的学习——如何使用Cheerio在Node.js中解析HTML

3,812 阅读5分钟

简介

传统上,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:选择每一个具有唯一的bar id的元素
  • $(":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博客上的所有特色文章,并将它们记录到我们的控制台。

以下是我们将如何实现这一目标。

  1. 了解LogRocket博客结构
  2. 下载网页标记
  3. 将下载的标记加载到一个新的Cheerio实例中
  4. 找到并过滤出需要的内容
  5. 将结果记录到控制台

了解网站结构

网页搜刮的第一步是了解网站的内容是如何安排的,也就是说,什么属性(class,id,href )是分配给你要访问的元素,等等。

Scraping Website Content with Cheerio

在我们的案例中,我们可以注意到,我们的目标内容是像下面这样排列的。

<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 ,你应该在控制台看到如下的输出。

Node Scrapper.js Output

结论

Cheerio是一个优秀的框架,用于在服务器端操作和爬取标记内容,而且它是轻量级的,实现了一个熟悉的语法。

本教程对如何在实际项目中开始使用Cheerio提供了一个深入的指导。

为了进一步参考,你也可以查看GitHub上的FeatRocket源代码。

谢谢你的阅读!

The postParsing HTML in Node.js with Cheerioappeared first onLogRocket Blog.