如何使用Node.js和JavaScript进行网页爬取

网络抓取工具和搜索引擎依靠网络爬行​​从网络中提取信息。因此,网络爬虫变得越来越流行。

在 Node.js 中使用正确的库构建网络蜘蛛很容易。在这里,您将学习如何使用最流行的网络爬虫库构建 JavaScript 网络爬虫。

在本教程中,您将了解 JavaScript 爬行的基础知识。此外,您将了解为什么在构建网络蜘蛛时 JavaScript 是一种很好的语言。您还将看到一些网络抓取的最佳实践

遵循本教程,成为使用 JavaScript 进行网络爬行的专家!让我们不要再浪费时间在 Node.js 中构建我们的第一个爬虫。

什么是网络爬虫?

网络爬虫,也称为网络蜘蛛,是一种系统地遍历一个或多个网站以收集信息的工具。具体来说,网络爬虫从已知 URL 列表开始。在抓取这些网页时,网络蜘蛛工具会发现其他 URL。

然后,网络蜘蛛会分析这些新的 URL,并继续进行 URL 发现过程。因此,网络爬取过程可以是无止境的。此外,与 URL 关联的一个网页可能比另一个网页更重要。因此,网络蜘蛛通常会为每个 URL 分配一个优先级

简而言之,网络爬虫的目标是在审查和排名网页时发现 URL。通常,搜索引擎使用网络蜘蛛来抓取网络。类似地,网络抓取工具使用网络爬取逻辑来查找要从中提取数据的网页

JavaScript 适合网络爬虫吗?

前端使用JavaScript,只能爬取同源内的网页那是因为您会通过AJAX下载网页。但是浏览器应用的同源策略缩小了 AJAX 的范围。

让我们通过一个例子更好地理解这一点。假设您的 JavaScript 网络蜘蛛在 example.com 的网页上运行。因此,该脚本只能抓取 example.com 域中的网页。

这并不意味着 JavaScript 不适合网络抓取。恰恰相反。感谢 Node.js,你可以在服务器上运行 JavaScript,避免前面提到的所有问题

因此,Node.js 允许您构建一个利用所有 JavaScript 优势的网络蜘蛛。详细来说,JavaScript 是一种易于编码的异步语言,受到数以千计的库的支持

现在让我们看看在网络爬虫方面如何使用 Node.js 的一些最佳实践。

Node.js 中网络爬虫的最佳实践

让我们深入探讨在 Node.js 中构建 JavaScript 网络爬虫的五个最佳实践。

使用您的 Web Spider 检索所有 URL

您应该考虑在抓取期间检索网页的整个链接列表毕竟,URL 是允许网络蜘蛛继续抓取站点的原因

只有一些可能会引起用户的兴趣,但将它们全部存储起来会使未来的迭代更容易。

此外,请考虑使用网站站点地图来查找所有索引 URL 的列表。

并行执行爬行

一次分析每个网页并不是一个有效的过程。按顺序对网站进行网络爬网需要花费大量时间。

幸运的是,您可以调整您的网络蜘蛛以并行运行以加快该过程JavaScript 支持异步逻辑。但请记住,实现它需要额外的逻辑。

让你的网络蜘蛛表现得像一个人

您的 JavaScript 网络爬虫应该以人的身份出现在网站上,而不是机器人。您可以通过设置适当的 HTTP 标头和超时来实现这一点。

目标是让您的 Node.js 网络蜘蛛像真实用户一样访问网页。

保持网络爬行逻辑简单

随着时间的推移,您的网络蜘蛛所针对的网站布局可能会发生很大变化。出于这个原因,您不应该过度设计您的 Node.js 网络爬虫

保持简单,以便您可以轻松地使其适应新的布局或站点。

保持网络爬虫运行

在 Node.js 上执行的网络爬虫不太可能消耗大量系统资源。

因此,您应该考虑让您的网络蜘蛛永远运行,尤其是在针对不断添加新页面的大型网站时。

准备工作

以下是简单的爬虫工作所需的列表:

  • Node.js 和 npm >= 8.0+ 如果您的系统上没有安装 Node.js,您可以从上面的链接下载 Node.js。

然后,你还需要以下两个 npm 库:

您可以使用以下命令将其添加到项目的依赖项中:

npm install axios cheerio

Axios是一个基于承诺的 JavaScript HTTP 客户端。它允许您发出 HTTP 请求并通过它们检索数据。

Cheerio是一个用于在 Node.js 中解析 HTML 和 XML 的 JavaScript 工具。它提供了用于遍历和操作网页DOM的 API。

现在让我们看看如何使用这两个库在 Node.js 中构建网络爬虫。

如何在 Node.js 中创建网络爬虫

您可以在此 GitHub 存储库中找到演示 JavaScript 网络爬虫的代码。克隆它并使用以下命令安装项目的依赖项:

git clone https://github.com/Tonel/web-crawler-nodejs 
cd web-crawler-nodejs 
npm install

按照本教程学习如何使用 JavaScript 构建 Node.js 网络爬虫应用程序!

首先,您需要设置一个 Node.js 服务器。如果您还没有克隆上面的 repo,请创建一个web-crawler-nodejs文件夹并使用下面的命令输入它。

mkdir web-crawler-nodejs 
cd web-crawler-nodejs

按照本教程学习如何使用 JavaScript 构建 Node.js 网络爬虫应用程序!

首先,您需要设置一个 Node.js 服务器。如果您还没有克隆上面的 repo,请创建一个web-crawler-nodejs文件夹并使用下面的命令输入它。

mkdir web-crawler-nodejs 
cd web-crawler-nodejs

现在,初始化一个 npm 应用程序:

npm init

遵循流程。package.json现在您的文件夹中应该有一个文件web-crawler-nodejs

您现在已准备好将axios和添加cheerio到项目的依赖项中。

npm install axios cheerio

创建一个server.js文件并初始化如下:

function main() { 
    console.log("Hello, World!") 
} 
 
main()

键入以下命令以启动server.jsNode.js 脚本:

node server.js

您现在应该在您的终端中看到以下消息:

Hello, World!

瞧!您刚刚初始化了一个 Node.js 应用程序。现在是定义网络爬虫逻辑的时候了。将它放在main()函数内部。

在这里,您将看到如何在https://scrapeme.live/shop/上执行网络爬虫。店里是这样的:

general_view_scrapeme_live_41f0226ba2

ScrapeMe 概览

scrapeme.live/shop只不过是一个简单的分页列表,列出了受 Pokemon 启发的产品。

让我们在 Node.js 中构建一个简单的网络爬虫来检索所有产品 URL。

首先,您需要从网页下载 HTML 内容。您可以按如下方式进行axios

const pageHTML = await axios.get("https://scrapeme.live/shop")

Axios 允许您在几行代码中执行 HTTP 请求以进行检索。pageHTML现在存储网页的 HTML 内容scrapeme.live/shop

cheerio是时候用下面的方法喂它了load()

const cheerio = require("cheerio"); 
 
// initializing cheerio 
const $ = cheerio.load(pageHTML.data)

恭喜!您现在可以开始执行网络爬虫了!

现在让我们提取爬取整个站点所需的所有分页链接的列表。右键单击包含页码的 HTML 元素,然后选择“检查”选项。

medium_devtools_inspect_scrapeme_live_8c1bf33d9c

选择“检查”选项以打开 DevTools 窗口

您的浏览器应打开以下 DevTools 窗口,并突出显示 DOM 元素:

medium_devtools_open_scrapeme_live_6d1f10a583

选择页码 HTML 元素后的 DevTools 窗口

在这里,您可以看到.page-numbers标识 DOM 中的分页 HTML 元素。您现在可以使用.page-numbers aCSS 选择器检索所有带有cheerio.

// retrieving the pagination URLs 
$(".page-numbers a").each((index, element) => { 
    const paginationURL = $(element).attr("href") 
})

如您所见,cheerio它的工作方式与 jQuery 一样。paginationURL将包含如下 URL:

https://scrapeme.live/shop/page/2/

现在,让我们检索与单个产品关联的 URL。右键单击产品的 HTML 元素。然后,使用“检查”选项打开 DevTools 窗口。这是你应该得到的:

medium_product_on_devtools_scrapeme_live_6cb295344b

选择产品 HTML 元素后的 DevTools 窗口

您可以使用 CSS 选择器检索产品 URL,li.product a.woocommerce-LoopProduct-link如下所示:

// retrieving the product URLs 
$("li.product a.woocommerce-LoopProduct-link").each((index, element) => { 
    const productURL = $(element).attr("href") 
})

现在,你只需要实现 JavaScript 爬取逻辑来遍历每个页面:

const axios = require("axios"); 
const cheerio = require("cheerio"); 
 
async function main(maxPages = 50) { 
    // initialized with the first webpage to visit 
    const paginationURLsToVisit = ["https://scrapeme.live/shop"]; 
    const visitedURLs = []; 
 
    const productURLs = new Set(); 
 
    // iterating until the queue is empty 
    // or the iteration limit is hit 
    while ( 
        paginationURLsToVisit.length !== 0 && 
        visitedURLs.length <= maxPages 
    ) { 
        // the current webpage to crawl 
        const paginationURL = paginationURLsToVisit.pop(); 
 
        // retrieving the HTML content from paginationURL 
        const pageHTML = await axios.get(paginationURL); 
 
        // adding the current webpage to the 
        // web pages already crawled 
        visitedURLs.push(paginationURL); 
 
        // initializing cheerio on the current webpage 
        const $ = cheerio.load(pageHTML.data); 
 
        // retrieving the pagination URLs 
        $(".page-numbers a").each((index, element) => { 
            const paginationURL = $(element).attr("href"); 
 
            // adding the pagination URL to the queue 
            // of web pages to crawl, if it wasn't yet crawled 
            if ( 
                !visitedURLs.includes(paginationURL) && 
                !paginationURLsToVisit.includes(paginationURL) 
            ) { 
                paginationURLsToVisit.push(paginationURL); 
            } 
        }); 
 
        // retrieving the product URLs 
        $("li.product a.woocommerce-LoopProduct-link").each((index, element) => { 
            const productURL = $(element).attr("href"); 
            productURLs.add(productURL); 
        }); 
    } 
 
    // logging the crawling results 
    console.log([...productURLs]); 
 
    // use productURLs for scraping purposes... 
} 
 
// running the main() function 
main() 
    .then(() => { 
        // successful ending 
        process.exit(0); 
    }) 
    .catch((e) => { 
        // logging the error message 
        console.error(e); 
 
        // unsuccessful ending 
        process.exit(1); 
    });

paginationURLsToVisitvisitedURLs确保网络蜘蛛不会多次访问同一页面。请注意,这productURLs是一个Set,因此它不能两次存储相同的产品 URL。

另外,请记住爬行逻辑可能是无限的。因此,您应该提供一种方法来限制网络蜘蛛可以访问的网页数量。在上面的脚本中,这发生在maxPages变量上。

瞧!您刚刚学习了如何使用 Node.js 和 JavaScript 构建一个简单的网络爬虫!

此时,您应该将抓取的 URL 保存到数据库中。这将允许您直接抓取已抓取的网页,而无需再次抓取它们。此外,您应该安排 JavaScript 爬取任务定期运行。

那是因为他们将来可能会添加、删除或更改产品。这些只是一些想法,本教程到此为止。重要的是要了解抓取通常只是更大过程中的第一步。

运行您的 JavaScript 网络爬虫,您将获得以下数据:

[ 
    "https://scrapeme.live/shop/Bulbasaur/", 
    "https://scrapeme.live/shop/Ivysaur/", 
    "https://scrapeme.live/shop/Venusaur/", 
 
    // ... 
     
    "https://scrapeme.live/shop/Nidoqueen/", 
    "https://scrapeme.live/shop/Nidorino/", 
    "https://scrapeme.live/shop/Nidoking/" 
]

你刚刚scrapeme.live/shop完全爬行了!

然而,顺序抓取网站可能不是性能的最佳解决方案。这就是为什么你应该让你的 JavaScript 网络爬虫并行工作。为此,请按照本教程了解如何使用 Node.js 并行爬网

另外,不要忘记并行爬取意味着在短时间内执行许多 HTTP 请求。您的目标站点可能会将您的网络蜘蛛识别为威胁并阻止它。为避免这种情况,您应该使用网络代理来轮换您的 IP。

结论

在本指南中,您将找到有关构建 JavaScript 网络爬虫应该了解的所有信息。具体来说,您了解了如何在 Node.js 中创建网络爬虫来抓取网站中的所有 URL。

您只需要合适的库,我们讨论了一些最流行的库。用它们实现一个 JavaScript 网络爬虫并不困难,只需要几行代码。

总结一下你学到的三个要点:

  • 什么是网络抓取。
  • 有关如何在 JavaScript 中执行网页抓取的提示。
  • 如何应用网络爬虫的基础知识从头开始在 Node.js 中构建网络蜘蛛。如果您喜欢这个,请查看Python 网络爬虫指南

类似文章