发布于 2026-01-06 0 阅读
0

使用 Crawlee 和 React 构建 Netflix 节目推荐器:一个网络爬虫和浏览器自动化库

使用 Crawlee 和 React 构建 Netflix 节目推荐系统

克劳利
一个网页抓取和浏览器自动化库

在本博客中,我们将指导您如何使用 Vite 和 Crawlee 构建一个网站,该网站可以根据 Netflix 剧集的类别和类型进行推荐。为此,我们将首先使用 Crawlee 从 Netflix 抓取剧集和类别信息,然后在用 Vite 构建的 React 应用中可视化抓取的数据。阅读完本指南后,您将拥有一个功能齐全的网页剧集推荐器,可以提供 Netflix 剧集推荐。

注:本文由我们社区成员撰写,投稿至 Crawlee Blog。如果您也想向 Crawlee Blog 投稿,请通过我们的Discord 频道联系我们。

克劳利和阿皮菲

这是 Apify 和 Crawlee 的官方开发者社区。| 8756 位成员

网站图标discord.com

我们开始吧!

先决条件

要使用 Crawlee,您需要 Node.js 16 或更高版本。

如果您喜欢 Crawlee 博客上的文章,请考虑在 GitHub 上给 Crawlee 点个星,这有助于我们接触并帮助更多开发者。

GitHub 标志 apify / crawlee

Crawlee 是一个基于 Node.js 的网络爬虫和浏览器自动化库,用于构建可靠的爬虫。它使用 JavaScript 和 TypeScript 编写,支持提取数据以用于人工智能、LLM、RAG 或 GPT 模型。Crawlee 还支持从网站下载 HTML、PDF、JPG、PNG 和其他格式的文件,并可与 Puppeteer、Playwright、Cheerio、JSDOM 和原始 HTTP 协议配合使用。它支持有头模式和无头模式,并支持代理轮换。

克劳利
一个网页抓取和浏览器自动化库

NPM 最新版本 下载 在 Discord 上聊天 构建状态

Crawlee 为您提供从头到尾的爬行和刮削解决方案,帮助您快速构建可靠的刮削器。

即使使用默认配置,您的爬虫程序也能伪装成人类,轻松躲过现代机器人防护系统的检测。Crawlee 为您提供抓取网页链接、收集数据并将其存储到磁盘或云端的工具,同时保持可配置性,以满足您的项目需求。

Crawlee 是以crawleeNPM 包的形式提供的。

👉在Crawlee 项目网站上查看完整文档、指南和示例👈

Crawlee for Python 现已开放给早期用户。🐍 👉 查看源代码 👈

安装

我们建议您访问Crawlee 文档中的入门教程以获取更多信息。

Crawlee 需要Node.js 16 或更高版本

使用 Crawlee CLI

体验 Crawlee 的最快方法是使用Crawlee CLI并选择“入门示例”。CLI…




您可以从官方网站安装最新版本的 Node.js。这份优秀的Node.js 安装指南会为您提供一些技巧,帮助您避免日后出现问题。

创建一个 React 应用

首先,我们将使用 Vite 创建一个 React 应用(用于前端)。在终端中运行以下命令即可创建:

npx create-vite@latest
Enter fullscreen mode Exit fullscreen mode

您可以查看Vite 文档,了解有关如何创建 React 应用的更多详细信息。

React 应用创建完成后,在 VS Code 中打开它。

反应

这将是你的 React 应用的结构。

npm run dev在终端中运行命令以启动应用程序。

维特和反应

将显示以下输出结果。

添加爬虫代码

根据我们的项目要求,我们将抓取 Netflix 上可用节目的类型和名称。

让我们开始编写爬虫代码吧。

安装

运行以下命令安装 Crawlee:

npm install crawlee
Enter fullscreen mode Exit fullscreen mode

Crawlee 使用 Cheerio 进行HTML 解析和静态网站抓取。虽然速度更快、资源占用更少,但它只能抓取不需要 JavaScript 渲染的网站,因此不适用于单页应用程序 (SPA)。

在本教程中,我们可以从 HTML 结构中提取数据,因此我们将使用 Cheerio。但对于从单页应用程序 (SPA) 或 JavaScript 渲染的网站中提取数据,Crawlee 也支持PlaywrightPuppeteer等无头浏览器库。

安装完库之后,就可以开始编写爬虫代码了。

src在目录中创建一个名为 `<filename>` 的文件scraper.js。整个爬虫代码都将创建在这个文件中。

抓取类型和节目

为了抓取类型和节目,我们将利用浏览器开发者工具来识别 Netflix 网站上针对类型元素的标签和 CSS 选择器。

我们可以捕获 HTML 结构并调用$(element)查询元素的子树。

类型

这里我们可以看到,流派名称是通过一个span带有nm-collections-row-nameclass 属性的标签捕获的。因此,我们可以使用span.nm-collections-row-name选择器来捕获此元素以及类似的元素。

标题

同样,我们可以观察到节目的标题是通过span带有nm-collections-title-nameclass 属性的标签捕获的。因此,我们可以使用span.nm-collections-title-name选择器来捕获此元素以及类似的元素。

// Use parseWithCheerio for efficient HTML parsing
const $ = await parseWithCheerio();

// Extract genre and shows directly from the HTML structure
const data = $('[data-uia="collections-row"]')
  .map((_, el) => {
    const genre = $(el)
      .find('[data-uia="collections-row-title"]')
      .text()
      .trim();
    const items = $(el)
      .find('[data-uia="collections-title"]')
      .map((_, itemEl) => $(itemEl).text().trim())
      .get();
    return { genre, items };
  })
  .get();

const genres = data.map((d) => d.genre);
const shows = data.map((d) => d.items);
Enter fullscreen mode Exit fullscreen mode

在上面的代码片段中,我们使用CheerioparseWithCheerio解析当前页面的 HTML 内容,并从 HTML 结构中提取信息genresshows

这将生成一个genres数组,shows其中分别存储了类型列表和节目列表。

数据存储

现在我们已经收集到了项目所需的所有数据,是时候存储或保存这些抓取的数据了。Crawlee 提供了一个用于存储数据的pushData()方法。

pushData ()方法会在项目目录中创建一个存储文件夹,并将抓取的数据以 JSON 格式存储。

await pushData({
      genres: genres,
      shows: shows,
    });
Enter fullscreen mode Exit fullscreen mode

这将把数组genres键分别保存shows为值genresshows

以下是我们将在项目中使用的完整代码:

import { CheerioCrawler, log, Dataset } from "crawlee";

const crawler = new CheerioCrawler({
  requestHandler: async ({ request, parseWithCheerio, pushData }) => {
    log.info(`Processing: ${request.url}`);

    // Use parseWithCheerio for efficient HTML parsing
    const $ = await parseWithCheerio();

    // Extract genre and shows directly from the HTML structure
    const data = $('[data-uia="collections-row"]')
      .map((_, el) => {
        const genre = $(el)
          .find('[data-uia="collections-row-title"]')
          .text()
          .trim();
        const items = $(el)
          .find('[data-uia="collections-title"]')
          .map((_, itemEl) => $(itemEl).text().trim())
          .get();
        return { genre, items };
      })
      .get();

    // Prepare data for pushing
    const genres = data.map((d) => d.genre);
    const shows = data.map((d) => d.items);

    await pushData({
      genres: genres,
      shows: shows,
    });
  },

  // Limit crawls for efficiency
  maxRequestsPerCrawl: 20,
});

await crawler.run(["https://www.netflix.com/in/browse/genre/1191605"]);
await Dataset.exportToJSON("results");
Enter fullscreen mode Exit fullscreen mode

现在,我们将运行 Crawlee 来抓取网站数据。在运行 Crawlee 之前,我们需要对package.json文件进行一些调整。我们将添加一个start脚本,指向该scraper.js文件以运行 Crawlee。

'scripts'在对象中添加以下代码:

"start": "node src/scraper.js"
Enter fullscreen mode Exit fullscreen mode

并保存。现在运行以下命令来启动 Crawlee 以抓取数据:

npm start
Enter fullscreen mode Exit fullscreen mode

运行此命令后,您将看到一个storage包含该key_value_stores/default/results.json文件的文件夹。抓取的数据将以 JSON 格式存储在此文件中。

现在我们可以使用这些 JSON 数据,并在App.jsx组件中显示它们来创建项目。

App.jsx组件中,我们将从文件jsonData中导入results.json

import { useState } from "react";
import "./App.css";
import jsonData from "../storage/key_value_stores/default/results.json";

function HeaderAndSelector({ handleChange }) {
  return (
    <>
      <h1 className="header">Netflix Web Show Recommender</h1>
      <div className="genre-selector">
        <select onChange={handleChange} className="select-genre">
          <option value="">Select your genre</option>
          {jsonData[0].genres.map((genres, key) => {
            return (
              <option key={key} value={key}>
                {genres}
              </option>
            );
          })}
        </select>
      </div>
    </>
  );
}

function App() {
  const [count, setCount] = useState(null);

  const handleChange = (event) => {
    const value = event.target.value;
    if (value) setCount(parseInt(value));
  };

  // Validate count to ensure it is within the bounds of the jsonData.shows array
  const isValidCount = count !== null && count <= jsonData[0].shows.length;

  return (
    <div className="app-container">
      <HeaderAndSelector handleChange={handleChange} />
      <div className="shows-container">
        {isValidCount && (
          <>
            <div className="shows-list">
              <ul>
                {jsonData[0].shows[count].slice(0, 20).map((show, index) => (
                  <li key={index} className="show-item">
                    {show}
                  </li>
                ))}
              </ul>
            </div>
            <div className="shows-list">
              <ul>
                {jsonData[0].shows[count].slice(20).map((show, index) => (
                  <li key={index} className="show-item">
                    {show}
                  </li>
                ))}
              </ul>
            </div>
          </>
        )}
      </div>
    </div>
  );
}

export default App;
Enter fullscreen mode Exit fullscreen mode

这段代码片段genre使用数组来显示类型列表。用户可以选择自己想要的类型,然后根据选择的类型,数组会显示 Netflix 上可用的网络剧集列表shows

请务必App.css从此处更新 CSS 文件:https://github.com/ayush2390/web-show-recommender/blob/main/src/App.css

并将此图像文件下载并保存到主项目文件夹中:下载图像

我们的项目准备就绪!

结果

现在,要在本地主机上运行您的项目,请运行以下命令:

npm run dev
Enter fullscreen mode Exit fullscreen mode

此命令将在本地主机上运行您的项目。以下是项目示例:

结果

项目链接 - https://github.com/ayush2390/web-show-recommender

在这个项目中,我们使用 Crawlee 来抓取 Netflix 的内容;同样,Crawlee 也可以用来抓取单页应用程序 (SPA) 和 JavaScript 渲染的网站。最棒的是,所有这些都可以用 JavaScript/TypeScript 编写代码,并且只使用一个库就能完成。

如果您想了解更多关于 Crawlee 的信息,请阅读Apify 提供的Crawlee 网络爬虫分步教程和相关文档。

文章来源:https://dev.to/crawlee/building-a-netflix-show-recommender-using-crawlee-and-react-160p