返回博客
指南
米赫内亚-奥克塔维安·马诺拉切2022年11月30日阅读时长:11分钟

如何使用 Python 配合 CURL 进行网页抓取

如何使用 Python 配合 CURL 进行网页抓取

如何在 Python 中使用 CURL?

简而言之,cURL主要是一款用于从服务器获取数据的命令行工具。我知道一提到命令行,事情可能看起来有些复杂。不过,我可以向你保证,正如你将在本文中看到的,实际上 cURL 可能是你作为程序员所用过的最简单的工具之一。

要在命令行中使用 cURL,只需打开一个新的终端窗口,输入 `curl`,然后输入要抓取的 URL。例如:

~ » curl 'https://api.ipify.org?format=json'

这条简单的命令正在调用 ipify 的 API,向服务器请求信息,就像传统浏览器所做的那样。该示例的输出将是一个包含您 IP 地址的 JSON 对象。虽然乍看之下可能不明显,但您刚刚为未来的网页爬虫搭建了基础架构。这一切仅需一行代码即可实现。

cURL 实际上是一个更高级的工具。如果您想进一步了解 cURL 的使用方法,可以查阅官方文档。您也可以使用 `--help` 选项来查看可用的各种选项。 

如何使用 cURL 获取 HTML 文件

在上例中,我们从 ipify 服务器收到的响应是一个 JSON 文件。这是因为该 API 接口返回的是 JSON 格式的数据。在网页抓取方面,你通常会遇到提供 HTML 文件的传统网站,此时你需要对这些文件进行解析并从中提取数据。

不过,目前我们的重点不在于数据处理,而在于数据提取。我们知道可以使用 cURL 抓取网站,但具体该如何操作呢?如果你还没好奇地尝试过,不妨直接让 cURL 访问任何你确定是传统 HTML 网站的通用 URL。我们以 httpbin.org 为例:

curl 'https://httpbin.org/forms/post'

在终端中输入该命令,你将收到纯文本 HTML 作为响应:

<!DOCTYPE html>
<html>
  <head>
  </head>
  <body>
  <!-- Example form from HTML5 spec http://www.w3.org/TR/html5/forms.html#writing-a-form's-user-interface -->
  <form method="post" action="/post">
   <p><label>Customer name: <input name="custname"></label></p>
   <p><label>Telephone: <input type=tel name="custtel"></label></p>
   <p><label>E-mail address: <input type=email name="custemail"></label></p>
   <fieldset>
    <legend> Pizza Size </legend>
    <p><label> <input type=radio name=size value="small"> Small </label></p>
    <p><label> <input type=radio name=size value="medium"> Medium </label></p>
    <p><label> <input type=radio name=size value="large"> Large </label></p>
   </fieldset>
   <fieldset>
    <legend> Pizza Toppings </legend>
    <p><label> <input type=checkbox name="topping" value="bacon"> Bacon </label></p>
    <p><label> <input type=checkbox name="topping" value="cheese"> Extra Cheese </label></p>
    <p><label> <input type=checkbox name="topping" value="onion"> Onion </label></p>
    <p><label> <input type=checkbox name="topping" value="mushroom"> Mushroom </label></p>
   </fieldset>
   <p><label>Preferred delivery time: <input type=time min="11:00" max="21:00" step="900" name="delivery"></label></p>
   <p><label>Delivery instructions: <textarea name="comments"></textarea></label></p>
   <p><button>Submit order</button></p>
  </form>
  </body>
</html>

如何在 Python 中使用 cURL 

正如你所见,使用 cURL 提取数据是一种非常简单的解决方案,无需实际编写代码。它仅仅是发送一条命令并接收一些信息而已。如果你想构建一个真正的网页抓取项目,就需要以某种方式利用收集到的数据。而作为程序员,我们希望通过编程方式对数据进行处理。这就是 Python 派上用场的地方。

为什么选择 Python 进行网页抓取项目

毫无疑问,Python 是最受欢迎的编程语言之一。它不仅功能强大,而且语法简单,非常适合初学者。此外,它拥有一个庞大的社区,成员们总是乐于伸出援手。因此,如果你在学习过程中遇到问题或陷入困境,不妨在 Stackoverflow 等平台上提问,肯定会有人为你提供帮助。 

就网络爬虫而言,Python 是一个绝佳的选择,因为它自带了丰富的库。正如本文后文将要介绍的那样,数据处理需要解析 HTML 文件,这样你才能“挖掘”其中的元素,并从特定网页中提取你所关注的信息。

使用 cURL 和 Python 进行网页抓取

到目前为止,我们已经了解了如何在终端中使用 curl,但究竟该如何将其与 Python 集成呢?其实,实现这一点的方法有多种。例如,你可以使用 Python 的 `os` 模块来发送终端命令:

import os 
curl = os.system(f'curl "https://httpbin.org/forms/post"') 
print(curl)

或者,你甚至可以围绕它编写自己的函数,并在整个项目中使用它:

import os  
def curl(website):     
    return os.system(f'curl "{website}"')
  
print(curl('https://httpbin.org/forms/post'))

不过,正如我之前所说,Python 最大的优势之一就是其丰富的包生态。由于 cURL 的功能非常丰富,如果要涵盖其所有特性,我们的函数就必须变得非常复杂。因此,与其重复造轮子,我建议我们使用现成的 Python cURL 集成包:PycURL。

什么是 PycURL 以及如何安装它

根据其官方网站介绍,PycURL是 cURL 库的一个接口,因此继承了 libcURL 的所有功能。简而言之,PycURL 就是我们在 Python 中使用 cURL 的工具。至于安装,与其他 Python 包一样,我们将使用 pip。如果你不熟悉 pip,它是一个 Python 包管理系统,Python 开发者经常使用它来快速安装依赖项。

话虽如此,要安装 PycURL,只需在终端中输入以下命令:

~ » pip install pycurl 

使用 BeautifulSoup 解析 HTML

既然我们正在讨论依赖项和 pip,不妨提一下 Python 社区为 HTML 解析开发了不少解决方案。其中最受欢迎的 HTML 解析包之一就是 BeautifulSoup。在 WebScrapingAPI,我们实际上专门写了一篇博客文章,介绍如何使用 Python 和 BeautifulSoup 提取和解析网页数据。 

与 PycURL 一样,安装 BeautifulSoup 只需一条命令:

~ » pip install beautifulsoup4

如何使用 Python 和 cURL 构建网页爬虫

既然我们已经讲完了理论部分,也掌握了如何在终端和 Python 中使用 cURL,那就让我们直接进入编码环节吧。在本节中,我们将通过构建一个实际的网页爬虫,学习如何在 Python 中使用 cURL。那么,废话不多说,让我们开始编码吧!

1. 设置目录

作为软件工程师,我们必须合理规划项目结构,确保项目不仅便于我们自己维护和阅读,也能让其他开发者轻松理解。为了保持项目井井有条,我们首先创建一个新目录来存放所有项目文件。打开一个新的终端窗口,使用 `cd` 命令进入 Desktop 目录,并创建一个名为 `py_scraper` 的新文件夹:

~ » cd desktop && mkdir py_scraper && cd py_scraper

让我简要说明一下我们到目前为止使用过的命令:

  • `cd` - 切换当前目录
  • `&&` - 仅当前一条命令执行成功时,才执行后续命令
  • `mkdir` - 创建新目录

在您常用的 IDE 中打开项目,并在 `py_scraper` 目录下创建一个名为“scraper.py”的新文件。提示:您也可以通过命令行使用以下命令完成此操作:

~/desktop/py_scraper » 执行 touch scraper.py && 运行 .

如果你正在使用 VSCode(就像我一样),现在应该会看到一个如下所示的窗口:

Dark 代码编辑器窗口已打开,显示一个名为 scraper.py 的空白 Python 文件

2. 安装软件包

此时,您的终端应位于 `py_scraper` 目录内。  在编写实际的爬虫程序之前,我们需要做的最后一步是安装之前介绍过的包以及另一个包。不过,我们希望将它们仅限制在 `py_scraper` 目录内(而不是全局安装)。为此,我们需要使用Python 的虚拟环境。虚拟环境允许我们将 Python 解释器、库和脚本进行隔离。

要在 `py_scraper` 目录下创建一个新的虚拟环境,请使用以下命令:

~/desktop/py_scraper » python3 -m venv env

这将创建一个新的 `env` 文件夹,在安装所需软件包之前,我们需要先激活该文件夹。请使用以下命令进行激活:

~/desktop/py_scraper » source env/bin/activate

既然您已经创建并激活了虚拟环境,接下来只需利用我们之前介绍过的 pip 命令安装所需的软件包即可。

~/desktop/py_scraper » pip install pycurl beautifulsoup4 certify

3. 创建 Python 和 cURL 网页爬虫

现在,您已经准备好使用 PycURL 和 BeautifulSoup 了。要使用这些包,我们需要先将它们导入到 `scraper.py` 文件中。只需在文件顶部添加以下代码片段:

import pycurl
import certify
from io import BytesIO
from bs4 import BeautifulSoup

# 所有逻辑代码都将写在这行下方

既然已经导入了所需包,接下来我们就来处理网页爬虫的逻辑部分。根据前面的讨论,我们知道需要涵盖两个方面:数据提取和数据处理。前者由 PycURL 负责,后者则由 BeautifulSoup 负责。为了使代码结构更清晰,我建议我们将这两个部分分开处理。

3.1. 使用 cURL 和 Python 抓取数据

这里所说的“抓取”,指的是网页抓取工具中的数据提取部分。基于这一点,并且了解如何通过调用 PycURL 接口在 Python 中使用 curl,让我们来编写代码:

# 设置全局变量
TARGET_URL = 'https://httpbin.org/forms/post'

# 使用 cURL 和 Python 通过 PycURL 从服务器收集数据
buffer = BytesIO()
curl = pycurl.Curl()
curl.setopt(curl.URL, TARGET_URL)
curl.setopt(curl.WRITEDATA, buffer)
curl.setopt(curl.CAINFO, certifi.where())
curl.perform()
curl.close()

# 使用 BytesIO 获取抓取的数据
body = buffer.getvalue()

# 保存输出结果并在终端中打印
data = body.decode('iso-8859-1')
print(data)

在上面的代码中,我们首先声明全局变量 `TARGET_URL`,用于存储我们要从中提取数据的网站的 URL。接下来,我们使用 `BufferIO` 创建一个缓冲区,初始化 PycURL 并设置两个选项:一个用于数据传输,另一个用于存储证书的文件名。最后,我们执行 curl 操作,并在之后关闭会话。 

就这样,你已经成功使用 Python 发出了 cURL 请求,并在控制台中打印出了 HTML 文件。现在,我们只需要处理第二部分,即数据处理。

3.2. 使用 Python 和 BeautifulSoup 解析 HTML

Having the raw data is redundant in web scraping, unless we perform some sort of action on it. As the most basic scope of any web scraper is to extract data from HTML. For our example, let us assume that we want to scrape all text inside the `<p>` elements from the `data` variable (that is currently holding all the scraped HTML). Here is how we do this using BeautifulSoup:

# 使用 BeautifulSoup 解析数据
soup = BeautifulSoup(data, 'html.parser')
# 使用 BeautifulSoup 查找元素
paragraphs = soup.find_all("p")
for p in paragraphs:
   print(p.text)

如您所见,使用 BeautifulSoup 只需 4 行代码即可提取所需结果。运行完整的脚本后,现在应能输出从目标网站收集的 HTML 文件中每个段落内的文本。 

那么,假设你已经按照说明操作,并且你的 `scraper.py` 文件中包含了本节中编写的所有代码,现在让我们回到终端并运行该脚本:

~/desktop/py_scraper » python3 scraper.py
客户姓名: 
电话号码: 
电子邮箱: 
  小份 
  中份 
  大份 
  培根 
  额外奶酪 
  洋葱 
  蘑菇 
首选送达时间: 
送餐说明: 
提交订单

结论

使用 Python 和 cURL 构建一个网页爬虫是一个非常有用的项目,也可以作为开发更大型网页爬取应用程序的起点。整合这两项技术的推荐方法是使用 PycURL。你也可以编写自己的接口或函数,在 Python 中与 cURL 进行交互。只是这样会多花一点时间和精力 :)。

希望这篇文章能成为您学习 curl、了解如何将其与 Python 结合使用以及构建基础网页爬虫的优质资源。此外,我邀请您对代码进行调整和修改,使其成为您自己的作品,这样您就能为作品集增添又一个项目。

关于作者
Mihnea-Octavian Manolache,全栈开发工程师 @ WebScrapingAPI
米赫内亚-奥克塔维安-马诺拉什全栈开发工程师

Mihnea-Octavian Manolache 是 WebScrapingAPI 的全栈及 DevOps 工程师,负责开发产品功能并维护确保平台平稳运行的基础设施。

开始构建

准备好扩展您的数据收集规模了吗?

加入2,000多家企业,使用WebScrapingAPI在无需任何基础设施开销的情况下,以企业级规模提取网页数据。