什么是网络爬虫?一位新工程师尝试从一个练习网站获取数据。

介绍

大家好!我是Mirai,一名新工程师,7月份加入公司,我是一名文科毕业生,没有任何工作经验,从7月份开始一直在系统开发部门工作。

这是继上一篇关于验证的文章之后的第二篇。

点击此处查看上一篇文章 ↓

Laravel 中的验证是什么?一位初级工程师从完全新手的角度进行解释。

今天的主题 网络爬虫 。

本文以完全初学者的视角撰写,结构如下。

  1. 什么是网络爬虫?它何时可以使用?
  2. 使用前需要注意的事项
  3. 静态页面和动态页面的区别
  4. 请在练习网站上试一试。

使用的语言/工具:Python 3.12 / requests / Beautiful Soup / Playwright(使用 uv 进行包管理)

我希望这对像我一样拥有文科背景的新工程师以及目前正在学习文科的工程师有所帮助!

网络爬虫究竟是什么?

网络抓取利用程序自动从网站上显示的信息中提取必要信息并将其整理成用户友好格式的。

通常情况下,我们会在浏览器中打开网页,浏览网页内容,然后复制我们需要的部分,对吧?网络爬虫就像是让程序帮你完成这个“打开→搜索→提取”的过程。

当我们分析该程序的功能时,它遵循以下流程:

  1. 访问网页并接收其内容(HTML)。
  2. 找到目标数据在 HTML 中的位置。
  3. 提取数据并保存到文件或其他类似位置。

类似的术语 爬取 。爬取是指“通过点击链接访问网页”,而抓取是指“从网页中提取信息”。搜索引擎通过爬取收集网页,然后分析这些网页的内容。

何时可以使用?

例如,在类似这样的情况下,它就很有用。

  • 数据分析与研究:收集并分析公开的公告和文章列表。
  • 监控您自己的网站:定期检查您网站上显示的内容以及是否存在失效链接。
  • 信息收集自动化:实现目前每天都需要手动复制的公开信息的自动化记录。

使用前需要注意的事项

网络爬虫虽然方便,但并非可以随意抓取任何网站的内容。开始之前,请务必检查以下几点。

  1. 在其服务条款中明确 禁止使用诸如网页抓取之类的自动化数据采集方法
  2. 检查您的 robots.txt 文件。robots.txt 是网站用来告知其他网站“请勿使用您的程序抓取此页面”的文件。您可以在 https://(网站域名)/robots.txt 查看该文件。但是,请记住 robots.txt 只是网站发出的一个请求,因此请将其与服务条款结合使用。
  3. 那些不会给服务器造成负载的 ,其访问速度远超人类操作。因此,必须考虑诸如分散请求时间和仅访问必要页面等因素。
  4. 处理获取的数据时务必谨慎。 获取的文本和图像可能受版权保护,并且可能包含个人信息。即使您已获取这些数据,也不意味着您可以随意发布或重新分发它们。

在本文中,我们将使用专为练习网络爬虫而设计的公开网站,因此您可以放心练习,无需担心这些问题。

在开始之前,让我们先来看看在进行网页抓取时应该了解的“页面类型”之间的区别。

静态页面和动态页面

静态页面 是指数据已经写入从服务器接收的 HTML 代码中的页面。您可以通过接收和读取 HTML 代码来获取数据。

动态页面 是指当接收到 HTML 时,数据不会以屏幕格式直接显示;浏览器必须执行 JavaScript 才能在屏幕上显示数据。

请注意,“静态”和“动态”这两个术语有时用来指代HTML是否在服务器端生成。在本文中,我们将无需执行JavaScript即可获取数据的页面称为“静态页面”,将必须执行JavaScript才能获取数据的页面称为“动态页面”。

问题在于像 Python 的 `requests` 这样的方法,它们只是简单地“接收 HTML”。由于 `requests` 不执行 JavaScript,因此它无法在动态页面的 HTML 中找到浏览器应该可见的数据。

这时 Playwright 。Playwright 是一款工具,它允许你从程序中运行一个真正的浏览器,并且可以在 JavaScript 执行后从页面中提取数据。

参考资料:Playwright for Python 官方文档(https://playwright.dev/python/)

在下一章中,我们将验证是否无法使用 `requests` 检索数据,然后尝试使用 Playwright 检索数据。

我们来试一下①:准备并确认“请求不能使用”

本教程将使用Quotes to Scrape ( https://quotes.toscrape.com/ ) 网站,这是一个专为练习网络爬虫而设计的网站。它展示了名人名言及其作者,并且还提供了一个JavaScript版本( https://quotes.toscrape.com/js/ ),该版本显示相同的内容。

本网站是“toscrape.com”的一部分,这是一个由Zyte(前身为Scrapinghub)提供的沙盒(练习区),Zyte是一家提供网络抓取服务的公司,该网站用于学习如何抓取数据。

这个网站是为练习而设计的,所以我们将用它来进行本次测试。在使用其他网站时,请务必事先查看服务条款和 robots.txt 文件。

参考资料:toscrape.com (https://toscrape.com/)

参考资料:Quotes to Scrape(https://quotes.toscrape.com/)

创造一个环境

对于 Python 包管理, uv。uv 是一个单一的工具,可以处理从安装 Python 可执行文件到管理库的所有操作。

安装方法因操作系统而异,请参考官方文档。

参考资料:uv官方文档(https://docs.astral.sh/uv/)

安装完 uv 后,在终端(Windows 系统下为命令提示符或 PowerShell)中运行以下命令:

uv init scraping-practice cd scraping-practice uv add requests beautifulsoup4 playwright uv run playwright install chromium

最后一行命令用于下载 Playwright 运行所依赖的浏览器(Chromium)。

尝试使用 Requests 库来检索它。

我们将使用 requests 来检索静态版本和动态版本,并统计我们找到的引用(div.quote)的数量。

在scraping-practice文件夹中创建一个名为compare.py的文件。

import time import requests from bs4 import BeautifulSoup urls = [ "https://quotes.toscrape.com/", # 静态页面 "https://quotes.toscrape.com/js/", # 动态页面 ] for url in urls: res = requests.get(url, timeout=10) soup = BeautifulSoup(res.text, "html.parser") quotes = soup.select("div.quote") print(f"{url} → {len(quotes)} 个项目") time.sleep(1) # 为服务器留出 1 秒的延迟

这是我运行程序后发生的情况。

https://quotes.toscrape.com/ → 10 条结果 https://quotes.toscrape.com/js/ → 0 条结果

虽然在浏览器中看起来一样,但动态版本显示的结果为 0。这是因为请求不会执行 JavaScript,所以应该显示在屏幕上的引用(div.quote)尚未包含在接收到的 HTML 中。这充分说明了静态和动态之间的区别。

我们来试试第二个方法:使用 Playwright 从动态页面中检索数据

现在开始正式操作。我们将从 所有 ,并将它们保存到 JSON 文件中。

使用开发者工具查找要检索的位置。

在编写任何代码之前,请先找出数据在 HTML 中的位置。 https://quotes.toscrape.com/js/ ,右键单击一条引文,然后选择“检查”以打开开发者工具。

仔细观察后,它原来是这样的。

  • 单引号:div.quote
  • 引文文本:span.text
  • 作者姓名:small.author
  • “下一步 →”按钮:li.next > a

编写代码

在scraping-practice文件夹中创建一个名为scrape_quotes.py的文件。

import json import time from urllib.parse import urljoin from playwright.sync_api import sync_playwright START_URL = "https://quotes.toscrape.com/js/" def main(): results = [] with sync_playwright() as p: # 启动无头浏览器 browser = p.chromium.launch(headless=True) page = browser.new_page() page.goto(START_URL) while True: # 使用 JavaScript 等待名言显示 page.wait_for_selector("div.quote") for quote in page.locator("div.quote").all(): text = quote.locator("span.text").inner_text() author = quote.locator("small.author").inner_text() results.append({"text": text, "author": author}) print(f"检索到 {page.url} 条(共 {len(results)} 条)") # 如果存在如果没有“下一页”按钮,则跳转到最后一页。`next_link = page.locator("li.next > a")` `if next_link.count() == 0: break time.sleep(1)` `# 留出 1 秒的间隔,以考虑服务器性能` `next_url = urljoin(page.url, next_link.get_attribute("href"))` `page.goto(next_url)` `browser.close()` `with open("quotes.json", "w", encoding="utf-8")` `as f: json.dump(results, f, ensure_ascii=False, indent=2)` `print(f"已完成:{len(results)} 个项目已保存到 quotes.json")` `if __name__ == "__main__": main()`

写完之后,运行以下命令。

uv 运行 python scrape_quotes.py

观点

  • `wait_for_selector`:在动态页面中,页面打开时可能没有任何数据可用。通过编写“等待直到报价显示完毕”之类的语句,可以防止错过数据。这是动态页面特有的概念,在 `requests` 中并不存在。
  • headless=True:此设置允许浏览器在不显示网页的情况下运行。如果将其设置为 False,则可以看到浏览器实际翻页,因此建议至少尝试一次。
  • sleep(1): 每次翻页后等待 1 秒。请注意,1 秒并非固定值,请根据您网站的服务条款和 robots.txt 设置进行调整。

结果

我运行程序时,数据检索过程是通过翻页的方式进行的。

已检索到 https://quotes.toscrape.com/js/(共 10 条) 已检索到 https://quotes.toscrape.com/js/page/2/(共 20 条)(已省略) 已检索到 https://quotes.toscrape.com/js/page/10/(共 100 条) 完成:100 条已保存到 quotes.json

最后, quotes.json 。其内容如下所示:(部分内容已省略)

[ { "text": "“我们创造的世界是我们思维过程的产物。...","author": "阿尔伯特·爱因斯坦" }, ... ]

每条引文的文本和作者姓名都一起保存了。我们成功地从之前请求结果为零的页面上检索到了数据!

概括

让我们回顾一下这次我们学到了什么。

  • 网络抓取是一种利用程序自动从网页中提取必要信息的技术。
  • 开始之前,请先阅读服务条款和 robots.txt 文件,以免服务器过载。
  • 动态页面可能无法显示可通过请求检索的数据。
  • Playwright 允许您运行浏览器并在显示后提取数据。

感谢您阅读至此!

参考:

• Playwright for Python 官方文档(https://playwright.dev/python/)

- UV官方文档(https://docs.astral.sh/uv/)

・Quotes to Scrape (https://quotes.toscrape.com/)

・toscrape.com (https://toscrape.com/)

如果您觉得这篇文章对您有帮助,请点个“赞”!
1
1
33
X Facebook Hatena书签 口袋

这篇文章的作者

关于作者