返回博客
指南
Mihnea-Octavian ManolacheLast updated on Mar 31, 20263 min read

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

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

任何网页抓取应用最基本的操作,就是先获取 HTML 文件,然后再对其进行处理。当然,实现这一目标的方法多种多样。不过,在今天的文章中,我们将探讨如何在 Python 中使用 CURL 进行网页抓取。以下是本文将涵盖内容的一小部分预览:

  • 什么是 cURL 以及如何通过命令行调用它
  • 如何使用 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 && code .

如果你使用的是 VSCode(就像我一样),现在会看到一个类似于下图的窗口:

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

# All our logic will go underneath this line

现在您已导入这些包,让我们来处理网络爬虫的逻辑。根据我们迄今为止的讨论,我们知道需要涵盖两个方面:数据提取和数据处理。第一部分由 PycURL 负责,第二部分由 BeautifulSoup 负责。为了更好的结构,我建议我们将每个部分单独处理。

3.1. 使用 cURL 和 Python 进行数据抓取

这里所说的“抓取”,指的是网页抓取工具中的数据提取部分。基于这一概念,并结合通过 PycURL 接口在 Python 中使用 curl 的知识,让我们编写代码:

# Setting global variables
TARGET_URL = 'https://httpbin.org/forms/post'

# Using cURL and Python to gather data from a server via 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()

# Using BytesIO to retrieve the scraped data
body = buffer.getvalue()

# Saving the output and printing it in terminal
data = body.decode('iso-8859-1')
print(data)

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

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

3.2. 使用 Python 和 BeautifulSoup 解析 HTML

在网页抓取中,如果不对原始数据进行处理,单纯获取数据是毫无意义的。任何网页抓取工具最基本的任务就是从 HTML 中提取数据。以本例为例,假设我们要从 `data` 变量(当前存储了所有抓取到的 HTML)中提取所有位于 `<p>` 标签内的文本。以下是使用 BeautifulSoup 实现的方法:

# Parsing data using BeautifoulSoup
soup = BeautifulSoup(data, 'html.parser')
# Finding elements using BeautifoulSoup
paragraphs = soup.find_all("p")
for p in paragraphs:
   print(p.text)

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

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

~/desktop/py_scraper » python3 scraper.py
Customer name: 
Telephone: 
E-mail address: 
  Small 
  Medium 
  Large 
  Bacon 
  Extra Cheese 
  Onion 
  Mushroom 
Preferred delivery time: 
Delivery instructions: 
Submit order

结论

使用 Python 和 cURL 构建网络爬虫是一个非常有用的项目,也可以作为开发更大规模网络爬取应用的起点。将这两项技术集成的推荐方法是使用 PycURL。你也可以编写自己的接口或函数来在 Python 中与 cURL 交互。这只是需要多花一点时间和精力 :)。

希望本文能成为您学习 cURL、掌握其与 Python 的结合使用以及构建基础网页爬虫的优质资源。此外,我邀请您对代码进行调整并加以改造,使其成为您自己的作品,这样您就能为个人作品集增添又一个项目。

关于作者
Mihnea-Octavian Manolache, 全栈开发工程师 @ WebScrapingAPI
Mihnea-Octavian Manolache全栈开发工程师

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

开始构建

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

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