构建 Python 内容聚合器

17 Mar 2025 | 阅读 17 分钟

这个基于项目的课程旨在教您如何使用 Python 和广受欢迎的 Django 框架从零开始创建一个内容聚合器。

每天网上发布的内容如此之多,访问多个网站和来源来阅读您喜爱主题的信息可能会非常耗时,这就是为什么内容聚合器如此受欢迎和有效的原因,因为您可以使用它们在一个地方查看所有最新的新闻和内容。

如果您正在为您的作品集寻找一个项目,或者想找到一种方法将未来的项目扩展到基本的 CRUD 功能之外,本课程将对您有所帮助。

Build a Content Aggregator in Python

您将学习如何

  • 处理 RSS feeds
  • 创建一个新的 Django 管理命令
  • 按计划自动运行您的自定义命令,以及如何使用单元测试来验证您的 Django 应用程序的功能

您将创建的演示内容

通过仔细遵循本指南,您可以在 Python 中创建自己的 pyCasts! 播客内容聚合器。

该程序将是一个单一的网页,列出 Talk Python to Me 和 The Only Python Podcast 在 Python 中的最新节目。完成本教程后,您可以通过向程序添加新的播客 feeds 来实践所学知识。

项目概述

为了向用户展示内容,您需要采取以下行动

  1. 配置项目
  2. 创建一个播客模型
  3. 设计主页。
  4. 分析一个 RSS 播客 feed
  5. 开发一个自定义的 Django 命令
  6. 添加更多 feeds
  7. 使用 django-apscheduler 来调度任务

在本教程中,您将逐一了解这些内容。现在,您将考虑用于上述操作的框架和技术。

Build a Content Aggregator in Python

您将学习使用 feedparser 库来解析和获取播客 RSS feeds 到您的应用程序中。通过 Django ORM,您将使用此模块将 feed 的数据整理到一个 Show 模型中,并将最新的节目保存到数据库中。

虽然您可以将此代码添加到脚本中定期手动运行,但这将违背使用聚合器节省时间的目的。相反,您将学习如何使用自定义管理命令,这是 Django 的一个功能。您将使用 Django 来执行您的代码以解析和保存数据。

django-apscheduler 模块将帮助您为函数调用(通常称为任务)创建时间表。然后可以使用 Django 管理界面查看哪些任务在何时运行。这将确保您的 feed 自动获取和解析,无需任何管理员干预。

前提条件

要充分利用本教程,您需要熟悉以下概念和工具

  • Python 基础知识;设置和使用虚拟环境
    • 基本的 HTML 和 CSS 知识
    • Django 的基本概念,包括其文件夹结构、URL 路由、迁移以及如何创建项目和应用程序

如果您直接开始,可能会学到更多。如果遇到困难,可以暂停并重读上述材料。

第 1 步:设置您的项目

完成此步骤后,您将完成环境的设置、依赖项的安装以及 Django 的配置。

首先创建您的项目目录,然后将目录更改到那里

现在您已进入项目目录,应该建立并激活您的虚拟环境。为此,请选择您最喜欢的工具。本示例使用 venv

当您的环境被激活并且 pip 已升级后,您必须安装必要的依赖项来完成该项目。您可以在教程的可下载源代码中找到一个 requirements.txt 文件

导航到源代码 setUps// 子目录来安装固定的依赖项。请确保将路径中的 path to requirements.txt> 替换为下载文件的实际路径

现在应该已经安装了 Django、feedparser、django-apscheduler 及相关依赖项。

现在您已具备开始所需的一切,请设置 Django 并开始创建。必须遵循以下四个步骤来完成此构建步骤

  1. 在 //pycasts 工作目录中启动一个 Django 项目。
  2. 为播客创建一个 Django 应用。
  3. 执行首次迁移
  4. 建立一个超级用户。

由于您熟悉 Django,我们将不会深入探讨这些步骤。您应该执行以下命令

在遵循 Django 的说明并完成超级用户帐户创建后,您需要在运行程序之前再做一个修改。将文件添加到 settings.py 文件中,尽管没有它程序仍然可以运行

是时候测试您全新的 Django 项目了。启动 Django 服务器

在您的浏览器中,访问 localhost:8000 查看 Django 的标准成功页面。

第 2 步:构建您的播客模型

此时,您的环境应该已经设置好,依赖项已经安装,并且 Django 应该运行顺畅。在本步骤结束时,您将为播客节目定义、测试并迁移一个模型到数据库。

您的 Show 模型应该不仅仅包含您作为开发者想要捕获的信息。此外,它还应该反映用户期望的信息。立即开始编写模型并深入代码可能是一个错误。如果这样做,您可能很快就会忽视用户的视角。毕竟,应用程序是为用户设计的,包括像您这样的开发者。

使用纸和笔可能会有所帮助,但您应该做对您有效的事情。

在编写数据库模型时,这可能是一种有用的策略,因为它可以防止您稍后添加额外的字段和执行不必要的迁移。

从用户和开发者的角度描述您的项目规格

作为用户,我希望

  • 有一个可访问的 URL,这样我就可以收听节目;
  • 有每个节目的标题;
  • 阅读每个节目的描述;
  • 知道每个节目何时发布;
  • 有一张播客的图片,这样我可以通过滚动来查找我最喜欢的播客;
  • 点击播客的标题

作为开发者,我希望:

- 每个节目都有一个独特的属性,这样我就可以防止数据库中出现重复的节目。

本指南的第 4 步将更详细地讨论这最后一个方面。

根据您提供的规格,您的播客应用中的 Show 架构应类似于以下内容

在将模型转移到数据库之前,还有一件事要做。在 Django 3.2 中,现在可以更改自动生成的主键的类型。与早期 Django 版本中的 Integer 默认值不同,新的默认值是 BigAutoField。现在运行迁移将导致以下错误

通过在 app.py 文件中的 PodcastsConfig 模块中添加额外的一行,您可以避免看到此错误

您的应用现在已设置为自动为每个模型分配一个主键。此外,您有一个代表数据的模型,并对其外观有一个愿景。现在您的 Show 表已添加到数据库中,您可以执行 Django 迁移

现在更改已经迁移,是时候测试它了!

由于本课程涵盖了很多内容,您将使用 Django 的内置框架进行单元测试。如果您愿意,在完成本教程中的项目后,可以随时使用 pytest 甚至其他框架重做单元测试。

您可以将它们添加到您的 podcasts//tests.py 文件中

使用.setUps()来定义上述代码中的一个示例 Show 对象。

为确保模型按预期执行,您可以测试几个 Show 属性。测试您在 Show.__str__() 中创建的模型字符串表示总是一个好主意。在调试代码时,您会看到字符串表示;如果它按预期呈现数据,调试将变得更简单。

您现在可以执行您的测试

如果您的测试成功运行,恭喜!现在您已经为您的内容聚合器奠定了坚实的基础,并拥有清晰的数据模型,可以继续前进了。是时候进入第三阶段了。

第 3 步:创建您的主页视图

到目前为止,您的 Show 模型应该在一个运行顺畅并通过单元测试的 Django 应用程序中实现。构建主页的 HTML 模板,添加必要的 CSS 和资源,将网站添加到您的 views.py 文件中,并测试网站是否正确渲染都在这个阶段完成。

静态和模板文件夹位于您下载的源代码 setUps// 文件夹中。您应该将这些目录复制到 pycasts// 项目根文件夹。不要忘记添加点 (.) 以将文件复制到当前工作目录,并确保将占位符 "source code setUps path" 替换为您在本地计算机上保存的访问路径

是时候将所有东西连接起来了,这样 Django 才知道包含 HTML 布局和静态文件的目录存在。

在本教程中,Django 3 使用 pathlib 进行文件路径处理。转到内容聚合器应用主菜单中的 settings.py 文件。向下滚动到 TEMPLATES 部分后,应将您之前创建的 templates// 文件夹添加到 DIRS 列表中。

虽然 Django 现在知道您的静态资源和模板的存在,但您还需要更多。在连接迄今为止所做的一切之前,您还需要完成一些事项

  • 使用 views.py 创建一个主页视图。
  • 构建 URL 路由
  • 增加单元测试

您建立主页视图和 URL 路径的顺序并不重要。两者都必须完成才能使应用程序正常运行,但您可以先创建您的视图类。

打开您的播客应用中的 views.py 文件,并用以下代码替换现有代码

Django 默认包含基于类的视图及其更著名的基于函数的视图。

要将播客系列传输到主页,您在上面的代码中使用了基于类的视图

  1. 为了遍历这些节目,您在第 7 行借鉴了 ListView 类。
  2. 第 11 到 14 行:您忽略了上下文信息,并按最近的十个系列进行筛选,如 pub_date(每个节目的发布日期)所示。否则,可能有数百个项目传递到网站,所以您希望在这里进行筛选。

此时给您的网站一个 URL。首先,您必须在您的播客应用中创建一个 urls.py 文件。

恭喜您走到这一步!您现在应该能够启动您的应用并查看主页了。和之前一样,使用命令 python manage.py runserver 启动您的应用程序,并导航到 localhost:8000。

主页看起来可以工作,但是没有内容。即使没有内容,单元测试仍然可以用来检查内容是否能正确显示。

您在第 2 步为模型开发了功能测试。此外,您还生成了一个 Show 项目以进行测试,使用了.setUps()。使用相同的测试节目数据,您可以检查您的主页模板是否按预期工作。

除了检查节目在主页上的显示方式之外。

对于像这样一个单页应用程序来说,这可能看起来有些过度,而且很可能确实如此。但您希望确保任何应用程序的未来更新都不会 disrupting 现有代码的发展。此外,如果您将此项目用作您作品集的一部分,您应该展示您理解这一点

以下文本指出了要添加到 podcasts//tests.py 文件中的新测试方法

和以前一样,您可以使用 Python manage.py test 来运行您的单元测试。如果此时您所有的测试都成功了,恭喜!

在此阶段,您成功开发了视图类,连接了 URL 路由,并建立了 HTML 模板和资源。此外,您还添加了更多成功的单元测试。现在您已准备好进行下一步。

第 4 步:解析播客 RSS Feeds

到目前为止,您的应用程序应该看起来相当不错了!您已经拥有开始贡献内容所需的一切。在本阶段结束时,您应该有信心能够使用 feedparser 库解析 RSS feed 并提取所需信息。

在开始解析 RSS feed 之前,它究竟是什么?

要使用 feedparser 解析一个 feed,您可以使用 parse()

您还可以访问一个名为.entries的特殊属性,该属性存在于已使用feedparser解析的feed中。这允许对feed的每个组件进行迭代。一旦您将播客节目添加到数据库中,就可以使用.entries来验证每个播客节目的指南。

注意:在实践以下代码片段之前,请先通读一遍。快速浏览此代码,以了解如何使用 feedparser。在下一步中,当您开发并应用 Django 自定义命令到您的项目时,您将编写类似的代码。

最好将其转换为一个 datetime 对象

您现在还不会将此代码放入文件中,因为您还没有一个可靠的机制在 Django 内部执行它。现在您熟悉了使用 feedparser,请探索使用自定义命令来运行您的解析函数。

第 5 步:构建一个自定义 Django 命令

虽然您在之前的步骤中学到了如何使用 feedparser,但您仍然缺少一种实用的方法来执行与 Django ORM 通信的代码。

自定义命令使用 manage.py 文件来执行您的代码。

包括您在上一步中创建的 RSS 解析代码,然后尝试向数据库中添加一些条目。立即更新您的 startjobs.py 代码

虽然这次运行自定义命令时屏幕上没有任何打印内容,但您现在应该可以在主页上看到来自 The Only Python Podcast 的播客节目。您可以试一试。您是否收到了类似这张图片的内容?如果是,那么恭喜您。一切都值得了。

在下一步中,您将在探索了自定义命令并设置了第一个 feed 后,学习如何添加更多的 feeds。

聚合器

此时,您用于解析“The Only Python Podcast”源的自定义命令应该可以正常工作了。在本步骤结束时,您将学会如何向您的自定义命令添加更多源。

现在您有一个自定义命令可以成功解析单个 feed,您可能会想为每个播客 feed 重复相同的代码。但那不是一种好的编码方式。您需要的是 DRY(不要重复自己)且更易于维护的代码。

您可以通过迭代一个 feed URL 列表,对每个项目使用解析代码。在大多数情况下,这会奏效。然而,由于 django-apscheduler 的工作方式,还有更可行的替代方案。下一节将对此进行更多讨论。

作为替代方案,您的代码需要重构,以包含一个解析方法和为每个需要解析的流提供一个单独的函数。然后,目前,您将独立调用这些方法。

注意:正如本课程开头所述,您现在只关注两个 feeds。一旦培训结束并且您理解了如何添加更多 feeds,您就可以深入实践,选择其他 RSS feeds 添加。

与此同时,《Speak Python to Me Podcast》的 Michael Kennedy 非常友善地允许在本指南中使用他的播客 feed。感谢您,Michael。

您现在将研究这在您的代码中会是什么样子

如前所述,通过将解析器代码与不同的 feeds 分离,使其可重用。您必须为您添加的每个额外 feed 添加一个新的顶级函数。在此示例中,您已分别使用 fetch_realpythons_shows() 和 fetch_talkpython_shows() 对 The Only Python Podcast 和 Talk Python to Me Podcast 实现了这一点。

现在您已经了解如何向程序中添加更多 feeds,可以进入下一阶段了,在那里您将研究如何自动化自定义命令并为其设置运行时间表。

第 7 步:使用 django-apscheduler 调度任务

到目前为止,您应该至少有两个 RSS feeds 排队并准备好在每次执行新的自定义命令时进行分析。

APScheduler 库通过 django-apscheduler 包在 Django 中实现。

注意:有关 APScheduler 和您可以使用的所有参数的更多信息,请参阅官方 APScheduler 文档。在项目的 GitHub 页面上,您可以获得有关 django-apscheduler 的更多信息。

在您的虚拟环境中,django-apscheduler 已经安装。您还必须将其添加到 settings.py 文件中的 INSTALLED_APPS 中,以便在您的应用程序中安装它

现在您的应用程序中已安装 django-apscheduler,您将简要了解其工作原理。有关更深入的解释,请参考官方文档。

任务是您想在自定义命令中运行的任务。您的应用程序总共将包含三个任务:一个用于您希望解析的每个网络广播源,第三个用于从信息库中删除旧的位置。

您的任务将由 django-apscheduler 包存储在数据库中,以及所有成功和失败的任务运行记录。作为网站管理员或开发人员,拥有这个历史记录非常好,因为它可以让您看到是否有任何任务失败。但是,如果这些记录不定期从数据库中删除,您的数据库会很快被填满,因此从数据库中删除任何以前的历史记录是最佳实践。这也会遵循一个时间表。

尽管任务历史将存储在数据库中,但为调试目的记录任何错误是一个好主意。可以将此代码添加到 settings.py 中,为您的应用程序添加一些基本的日志记录设置

您的自定义命令类现在应该看起来像这样

和以前一样,可以使用 `python manage.py startjobs` 在一个终端中执行自定义命令。在另一个终端进程中启动您的 Django 服务器。现在,您可以在管理仪表板上浏览历史记录,并看到您的任务已经注册

Build a Content Aggregator in Python

在最后一个阶段有很多事情要做,但您完成了,现在您的应用可以工作了!您已经掌握了使用 django-apscheduler 自动调度执行自定义命令的方法。这可不是一件容易的事。干得好!

从零开始创建一个项目,比如内容聚合器,从来都不是一件快速或容易的事情,因此您应该为坚持到底而感到自豪。无论您的资历有多深,尝试一些新的、有点挑战性的东西只会帮助您作为一名开发人员不断进步。

结论

您在这个基于项目的教程中涵盖了很多内容。干得好!

在本教程中,您学习了如何

  • 使用后端按灵活的时间表自动化您自己的命令;
  • 使用 feedparser 与 RSS feeds 交互;
  • 构建和使用自定义管理命令;
  • 将核心单元测试整合到您的 Django 程序中