开始使用 JavaScript 进行网页抓取

Web 抓取是编码世界中最有趣的事情之一。

什么是网页抓取?

为什么它甚至存在?

让我们找出答案。

什么是网页抓取?

Web 抓取是一项从网站中提取数据的自动化任务。

网络抓取有很多应用。 提取产品的价格并与不同的电子商务平台进行比较。 从网上获取每日报价。 构建您自己的搜索引擎,例如 Google、Yahoo 等。不胜枚举。

使用网络抓取,您可以做的比您想象的要多。 一旦你了解了如何从网站中提取数据,你就可以对数据做任何你想做的事。

从网站提取数据的程序称为网络抓取工具。 您将学习用 JavaScript 编写网络抓取工具。

网页抓取主要有两个部分。

  • 使用请求库和无头浏览器获取数据。
  • 解析数据以从数据中提取我们想要的确切信息。

事不宜迟,让我们开始吧。

项目设置

我假设您已经安装了 Node,如果没有,请查看 NodeJS 安装指南。

我们将使用 node-fetch 和 cheerio 包在 JavaScript 中进行网页抓取。 让我们使用 npm 设置项目以使用第三方包。

让我们快速查看完成设置的步骤。

  • 创建一个名为 web_scraping 的目录并导航到该目录。
  • 运行命令 npm init 来初始化项目。
  • 根据您的喜好回答所有问题。
  • 现在,使用命令安装包
npm install node-fetch cheerio

让我们看看已安装的软件包。

节点获取

包 node-fetch 将 window.fetch 带到节点 js 环境中。 它有助于发出 HTTP 请求并获取原始数据。

欢呼声

包裹 欢呼声 用于从原始数据中解析和提取必要的信息。

两个包 node-fetch 和 cheerio 足以用 JavaScript 进行网页抓取。 我们不会看到包提供的每一种方法。 我们将看到网络抓取的流程以及该流程中最有用的方法。

您将通过这样做来学习网络抓取。 那么,让我们开始工作吧。

刮板球世界杯名单

在本节中,我们将进行实际的网络抓取。

我们在提取什么?

根据本节的标题,我想您很容易猜到。 是的,你想的都是对的。 让我们提取到目前为止所有的板球世界杯冠军和亚军。

  • 在项目中创建一个名为 extract_cricket_world_cups_list.js 的文件。
  • 我们将使用 维基百科板球世界杯 页面以获取所需的信息。
  • 首先,使用 node-fetch 包获取原始数据。
  • 下面的代码获取上述维基百科页面的原始数据。
const fetch = require("node-fetch");

// function to get the raw data
const getRawData = (URL) => {
   return fetch(URL)
      .then((response) => response.text())
      .then((data) => {
         return data;
      });
};

// URL for data
const URL = "https://en.wikipedia.org/wiki/Cricket_World_Cup";

// start of the program
const getCricketWorldCupsList = async () => {
   const cricketWorldCupRawData = await getRawData(URL);
   console.log(cricketWorldCupRawData);
};

// invoking the main function
getCricketWorldCupsList();

我们从 URL 中获取了原始数据。 现在,是时候从原始数据中提取我们需要的信息了。 让我们使用包 cheerio 来提取数据。

  章节互动故事兑换代码:立即兑换

使用 cheerio 提取涉及 HTML 标记的数据是小菜一碟。 在进入实际数据之前,让我们看一些使用 cheerio 解析的示例数据。

  • 使用 cheerio.load 方法解析 HTML 数据。
const parsedSampleData = cheerio.load(
      `<div id="container"><p id="title">I'm title</p></div>`
   );
  • 我们已经解析了上面的 HTML 代码。 如何从中提取 p 标签内容? 它与 JavaScript DOM 操作中的选择器相同。

console.log(parsedSampleData(“#title”).text());

您可以根据需要选择标签。 您可以从 cheerio官网.

  • 现在,是时候提取世界杯名单了。 要提取信息,我们需要知道信息位于页面上的 HTML 标记。 前往 板球世界杯维基百科页面 并检查页面以获取 HTML 标记信息。

这是完整的代码。

const fetch = require("node-fetch");
const cheerio = require("cheerio");

// function to get the raw data
const getRawData = (URL) => {
   return fetch(URL)
      .then((response) => response.text())
      .then((data) => {
         return data;
      });
};

// URL for data
const URL = "https://en.wikipedia.org/wiki/Cricket_World_Cup";

// start of the program
const getCricketWorldCupsList = async () => {
   const cricketWorldCupRawData = await getRawData(URL);

   // parsing the data
   const parsedCricketWorldCupData = cheerio.load(cricketWorldCupRawData);

   // extracting the table data
   const worldCupsDataTable = parsedCricketWorldCupData("table.wikitable")[0]
      .children[1].children;

   console.log("Year --- Winner --- Runner");
   worldCupsDataTable.forEach((row) => {
      // extracting `td` tags
      if (row.name === "tr") {
         let year = null,
            winner = null,
            runner = null;

         const columns = row.children.filter((column) => column.name === "td");

         // extracting year
         const yearColumn = columns[0];
         if (yearColumn) {
            year = yearColumn.children[0];
            if (year) {
               year = year.children[0].data;
            }
         }

         // extracting winner
         const winnerColumn = columns[3];
         if (winnerColumn) {
            winner = winnerColumn.children[1];
            if (winner) {
               winner = winner.children[0].data;
            }
         }

         // extracting runner
         const runnerColumn = columns[5];
         if (runnerColumn) {
            runner = runnerColumn.children[1];
            if (runner) {
               runner = runner.children[0].data;
            }
         }

         if (year && winner && runner) {
            console.log(`${year} --- ${winner} --- ${runner}`);
         }
      }
   });
};

// invoking the main function
getCricketWorldCupsList();

而且,这是抓取的数据。

Year --- Winner --- Runner
1975 --- West Indies --- Australia
1979 --- West Indies --- England
1983 --- India --- West Indies
1987 --- Australia --- England
1992 --- Pakistan --- England
1996 --- Sri Lanka --- Australia
1999 --- Australia --- Pakistan
2003 --- Australia --- India
2007 --- Australia --- Sri Lanka
2011 --- India --- Sri Lanka
2015 --- Australia --- New Zealand
2019 --- England --- New Zealand

酷😎,是吗?

  如何访问我的 Epic Games 帐户

抓取模板

从 URL 获取原始数据在每个网络抓取项目中都很常见。 唯一改变的部分是根据要求提取数据。 您可以尝试将以下代码作为模板。

const fetch = require("node-fetch");
const cheerio = require("cheerio");
const fs = require("fs");
// function to get the raw data
const getRawData = (URL) => {
   return fetch(URL)
      .then((response) => response.text())
      .then((data) => {
         return data;
      });
};
// URL for data
const URL = "https://example.com/";
// start of the program
const scrapeData = async () => {
   const rawData = await getRawData(URL);
   // parsing the data
   const parsedData = cheerio.load(rawData);
   console.log(parsedData);
   // write code to extract the data
   // here
   // ...
   // ...
};
// invoking the main function
scrapeData();

结论

您已经学习了如何抓取网页。 现在,轮到你练习编码了。

我还建议查看流行的网络抓取框架以探索基于云的网络抓取解决方案。

快乐编码🙂

喜欢阅读这篇文章吗? 与世界分享怎么样?