如何使用 Python cURL?

curl 是一款在命令行环境下运行的 HTTP 客户端工具。它广泛应用于从命令行发送 HTTP 请求。
curl 可用于编写网络爬虫脚本、检测网站运行状态以及从命令行下载文件。

由于其便捷性,curl 被多种编程语言所采用。本文旨在介绍
curl 的基本概念及其在 Python 中的应用方法。

什么是 cURL?

根据官方网站,cURL 代表 “客户端 URL”。它是一个命令行工具和程序库,支持使用各种应用层网络协议(如 HTTP、HTTPS、FTP 和 IMAP)传输数据。

cURL
非常流行,已被安装在包括收音机、电视、路由器、打印机和计算机等在内的超过 100 亿台设备上。它是完全免费且开源的,其源代码在
GitHub 上公开。

cURL 的应用场景

cURL
功能强大且用途广泛。以下列出了一些最常见的应用场景。尽管并非全部,但以下例子能很好地展示其广泛用途:

  • API 测试:可以验证 API 是否正常运行,并针对给定请求返回正确的数据。
    此外,还可用于检查 API 的响应速度。您可以编写脚本定期检查 API
    的健康状态,并在出现问题时发送警报。
  • 网页抓取:cURL
    可以自动化地从网站提取数据。它可以与多种编程语言结合使用,也可以作为
    Bash 命令执行。使用 cURL,您可以动态获取网站数据。从返回的
    HTML 中,可以解析和提取所需信息。如果您对网页抓取感兴趣,不妨了解一下
    techblik.com 的 Web Scraping API,它能简化数据抓取流程。
  • 数据下载:通过 cURL,您可以将请求的响应保存到文件中。这些响应可能是
    API 返回的数据或来自服务器的文件。实际上,将响应写入文件即等同于下载文件。由于
    cURL 是一个命令行工具,您可以自动化这个过程,一次下载大量文件。

如何在 Python 中使用 cURL (PycURL)

安装 PycURL

要在 Python 中使用 cURL,我们需要借助 PycURL 库。PycURL 是
cURL 库的 Python 接口,它在 cURL
库的基础上构建了一个轻量级包装器,这使得 PycURL 在处理请求时比其他库如
urllib 和 requests 更快。首先需要安装 PycURL。虽然安装方法有多种,但最简单的方式是通过 pip 命令:

pip install PycURL

在 Ubuntu 22.04 环境下,您可能需要在安装 PycURL 前安装额外的工具。在尝试使用
pip 安装 PycURL 之前,请先执行以下命令:

sudo apt install libcurl4-openssl-dev libssl-dev

发送简单的 GET 请求

要发送请求,首先需要创建一个 Python 脚本来编写代码。使用文本编辑器打开该文件,例如
Vim:

vim pycurl.py

其中 pycurl.py 是您要编写代码的文件名,您可以随意命名。

接下来,从 PycURL 模块导入 Curl 类:

from pycurl import Curl

导入 PycURL 后,我们还需要从 io 模块导入 BytesIO。它用于创建一个缓冲区,存储
PycURL 的响应数据。

from io import BytesIO

然后我们创建一个新的 Curl 实例:

c = Curl()

接下来,我们实例化一个 BytesIO 对象来创建一个新的缓冲区。PycURL
本身没有内置的存储机制来存储响应。所以我们需要创建一个缓冲区,并告诉它将数据写入到哪里。

buffer = BytesIO()

创建缓冲区后,就可以在客户端对象上设置选项。在本例中,我们需要设置两个选项:
第一个是请求的 URL,第二个是响应内容要写入的位置。代码如下:

    
c.setopt(c.URL, 'http://pycurl.io/')
c.setopt(c.WRITEDATA, buffer)
    
  

完成上述设置后,通过调用客户端对象的 perform
方法来发起请求,然后使用 close 方法关闭连接。

    
c.perform()
c.close()
    
  

要获取响应,调用缓冲区对象的 getvalue() 方法并对其解码。然后将其打印到控制台。

    
body = buffer.getvalue()
print(body.decode('iso-8859-1'))
    
  

您的完整文件内容应如下所示:

    
from pycurl import Curl
from io import BytesIO

# 创建一个 pycUrl 实例
c = Curl()
buffer = BytesIO()

c.setopt(c.URL, 'http://pycurl.io/')
c.setopt(c.WRITEDATA, buffer)

# 发送请求
c.perform()

# 关闭连接
c.close()

body = buffer.getvalue()
print(body.decode('iso-8859-1'))
    
  

执行脚本后,您将得到如下输出:

发送 POST 请求

要发送 POST 请求,需要设置 cURL 客户端对象的 POSTFIELDS
选项。以下是一个向 JSON Placeholder API 发送 POST 请求的示例:

    
from io import BytesIO
from json import dumps
from pycurl import Curl

# 创建一个 pycUrl 实例
c = Curl()
buffer = BytesIO()

# 创建一个数据字典
data = {
    'userId': 1,
    'title': 'Lorem Ipsum',
    'body': 'Dolor sit amet'
}

# 将数据编码为 JSON
encoded_data = dumps(data)

# 设置请求选项
c.setopt(c.URL, 'https://jsonplaceholder.typicode.com/posts')
c.setopt(c.HTTPHEADER, ['Accept: application/json', 'Content-Type: application/json'])
c.setopt(c.POSTFIELDS, encoded_data)
c.setopt(c.WRITEDATA, buffer)

# 发送请求
c.perform()

# 关闭连接
c.close()

body = buffer.getvalue()
print(body.decode('iso-8859-1'))
    
  

在上面的代码中,我们创建了一个字典对象,其中包含了要作为请求的一部分发送的数据。
然后,将数据编码为 JSON,并通过设置 POSTFIELDS
选项将其作为负载附加到请求中。我们还指定了标头,以指明请求内容类型和接受的响应数据类型。运行代码后,您将得到类似于如下的响应:

将响应写入文件

您还可以将文件缓冲区传递给 cURLWRITEDATA
选项,这样可以将响应数据写入到文件中。下面的例子说明了这个概念:

    
from pycurl import Curl

file_name="output.json"

# 以写入模式打开文件
with open(file_name, 'wb') as f:
    
    # 创建一个 Curl 实例
    c = Curl()

    # 设置请求选项
    c.setopt(c.URL, 'https://jsonplaceholder.typicode.com/users/1')
    c.setopt(c.HTTPHEADER, ['Accept: application/json'])
    c.setopt(c.WRITEDATA, f)

    # 发送请求
    c.perform()

    # 关闭连接
    c.close()

    print(f'Wrote output to {file_name}')
    
  

PycURL 的替代方案

PycURL 只是在 cURL
库之上提供了一个轻薄的封装层,这使得它可以实现高度定制,因为您可以更好地控制底层的操作。

然而,它使用起来相对复杂,更适合高级开发人员。通常,您可能需要一个更简单的
PycURL 替代方案。在本节中,我们将讨论一些替代方案。

#1. 其他库

除了 PycURL,Python 还有其他可用于发送请求的库,包括
requests 库和 urllib 库。它们都是 PycURL 的流行且更简单的替代方案。

#2. 其他语言

cURL 在其他语言中也有相应的接口实现。一个流行的用于转换
cURL 网站是 Curl Converter。通过 Curl Converter,您可以编写
cURL 命令来发送请求,它会自动将您的命令转换为任何选定的编程语言。您也可以直接在终端中调用
cURL 命令或编写 Bash 脚本来执行。

结论

本文介绍了 cURL 的基本概念,并演示了如何使用 PycURL 模块在
Python 中使用它。此外,我们还探讨了 PycURL 的替代方案,比如
requests 模块和使用不同的编程语言。

接下来,我们将通过实例来演示 cURL 命令的用法。