pycurl 实例:Python 如何直接输出 curl 请求结果 – wiki基地

Python 如何直接输出 curl 请求结果:深入 PycURL 实例

在使用 Python 进行网络编程时,我们经常需要发送 HTTP 请求,获取服务器返回的数据。虽然 requests 库以其简洁易用著称,但有时我们需要更底层、更灵活的控制,或者需要利用 curl 命令的一些高级特性。这时,pycurl 库就派上了用场。pycurl 是一个 Python 接口,它允许我们直接调用 libcurl 库,从而获得对网络请求的细粒度控制。

本文将深入探讨如何使用 pycurl 库直接输出 curl 请求的结果,包括响应头和响应体。我们将从 pycurl 的基本安装和配置开始,然后通过一系列示例演示如何执行不同的 HTTP 请求,并捕获和处理响应数据,最后讨论一些高级用法和常见问题。

1. PycURL 的安装与配置

在使用 pycurl 之前,你需要先安装它。可以使用 pip 命令进行安装:

bash
pip install pycurl

在安装过程中,可能会遇到一些问题,尤其是在 Linux 系统上。这通常是由于缺少 libcurl 库或者相关的开发包。以下是一些可能的解决方案:

  • Ubuntu/Debian:
    bash
    sudo apt-get update
    sudo apt-get install libcurl4-openssl-dev

  • CentOS/RHEL:
    bash
    sudo yum install curl-devel

  • macOS:
    通常 macOS 已经预装了 curl,但可能需要安装 Xcode Command Line Tools。

安装完成后,可以通过以下方式验证 pycurl 是否成功安装:

“`python
import pycurl

print(pycurl.version)
“`

如果成功打印出 pycurl 的版本信息,则表示安装成功。

2. 基本的 PycURL 请求与响应输出

pycurl 的基本用法是创建一个 Curl 对象,设置相关的选项,然后执行请求。以下是一个简单的示例,展示如何发送一个 GET 请求,并将响应头和响应体直接输出到控制台:

“`python
import pycurl
import io

def fetch_url(url):
“””
使用 pycurl 发送 GET 请求并输出响应头和响应体。
“””

buffer = io.BytesIO()

c = pycurl.Curl()
c.setopt(c.URL, url)

# 设置 WriteFunction,将响应体写入 buffer
c.setopt(c.WRITEDATA, buffer)

# 设置 HEADERFUNCTION,直接打印响应头
def header_function(header_line):
    print(header_line.decode('utf-8').rstrip())  # 解码并去除尾部换行符
    return len(header_line)

c.setopt(c.HEADERFUNCTION, header_function)

try:
    c.perform()
    body = buffer.getvalue().decode('utf-8')
    print("\nResponse Body:\n")
    print(body)

    # 获取响应状态码
    response_code = c.getinfo(pycurl.RESPONSE_CODE)
    print(f"\nResponse Code: {response_code}")

except pycurl.error as e:
    print(f"An error occurred: {e}")
finally:
    c.close()

if name == ‘main‘:
url = “https://www.example.com”
fetch_url(url)
“`

代码解释:

  • import pycurlimport io: 导入必要的库。pycurl 用于发起 HTTP 请求,io 用于创建内存中的缓冲区,用于存储响应体。
  • buffer = io.BytesIO(): 创建一个 BytesIO 对象,用于存储响应体。
  • c = pycurl.Curl(): 创建一个 Curl 对象,这是 pycurl 的核心对象,用于配置和执行请求。
  • c.setopt(c.URL, url): 设置请求的 URL。
  • c.setopt(c.WRITEDATA, buffer): 设置 WRITEDATA 选项,将响应体写入 buffer 中。 如果没有设置这个选项,默认响应体会被忽略。
  • header_function(header_line): 这是一个自定义的函数,用于处理响应头。它接收每一行响应头,并将其解码为字符串并打印到控制台。HEADERFUNCTION 必须返回处理的字节数,通常是 len(header_line)
  • c.setopt(c.HEADERFUNCTION, header_function): 设置 HEADERFUNCTION 选项,将 header_function 函数设置为响应头处理函数。 如果没有设置这个选项,默认响应头会被忽略。
  • c.perform(): 执行请求。
  • body = buffer.getvalue().decode('utf-8'):buffer 中获取响应体,并将其解码为 UTF-8 字符串。
  • print(body): 打印响应体。
  • response_code = c.getinfo(pycurl.RESPONSE_CODE): 获取响应状态码。 c.getinfo() 函数可以获取许多有用的信息,例如连接时间、下载速度等。
  • c.close(): 关闭 Curl 对象,释放资源。

运行结果:

运行上述代码,你将看到类似以下的输出:

“`
HTTP/1.1 200 OK
Age: 192519
Cache-Control: max-age=604800
Content-Type: text/html; charset=UTF-8
Date: Thu, 02 Nov 2023 08:36:46 GMT
Etag: “3147526947”
Expires: Thu, 09 Nov 2023 08:36:46 GMT
Last-Modified: Thu, 17 Oct 2019 07:18:26 GMT
Server: ECS (nyb/1550)
Vary: Accept-Encoding
X-Cache: HIT
Content-Length: 1256

Response Body:




Example Domain



Example Domain

This domain is for use in illustrative examples in documents. You may use this
domain in literature without prior coordination or asking for permission.

More information…


Response Code: 200
“`

可以看到,响应头和响应体都成功地打印到了控制台。

3. 发送 POST 请求并输出结果

除了 GET 请求,pycurl 也可以发送 POST 请求。以下是一个示例,展示如何发送一个 POST 请求,并将请求体作为 JSON 数据发送:

“`python
import pycurl
import io
import json

def post_data(url, data):
“””
使用 pycurl 发送 POST 请求并输出响应头和响应体。
“””

buffer = io.BytesIO()

c = pycurl.Curl()
c.setopt(c.URL, url)

# 设置请求类型为 POST
c.setopt(c.POST, 1)

# 将数据转换为 JSON 字符串
json_data = json.dumps(data)

# 设置请求体
c.setopt(c.POSTFIELDS, json_data)

# 设置 Content-Type 头
c.setopt(c.HTTPHEADER, ['Content-Type: application/json'])

# 设置 WriteFunction,将响应体写入 buffer
c.setopt(c.WRITEDATA, buffer)

# 设置 HEADERFUNCTION,直接打印响应头
def header_function(header_line):
    print(header_line.decode('utf-8').rstrip())  # 解码并去除尾部换行符
    return len(header_line)

c.setopt(c.HEADERFUNCTION, header_function)

try:
    c.perform()
    body = buffer.getvalue().decode('utf-8')
    print("\nResponse Body:\n")
    print(body)

    # 获取响应状态码
    response_code = c.getinfo(pycurl.RESPONSE_CODE)
    print(f"\nResponse Code: {response_code}")

except pycurl.error as e:
    print(f"An error occurred: {e}")
finally:
    c.close()

if name == ‘main‘:
url = “https://httpbin.org/post” # 使用 httpbin 模拟 POST 请求
data = {“name”: “John Doe”, “age”: 30}
post_data(url, data)
“`

代码解释:

  • c.setopt(c.POST, 1): 设置请求类型为 POST。
  • json_data = json.dumps(data): 将 Python 字典转换为 JSON 字符串。
  • c.setopt(c.POSTFIELDS, json_data): 设置请求体为 JSON 字符串。
  • c.setopt(c.HTTPHEADER, ['Content-Type: application/json']): 设置 Content-Type 头,告知服务器请求体是 JSON 格式。

运行结果:

运行上述代码,你将看到类似以下的输出:

“`
HTTP/1.1 200 OK
Date: Thu, 02 Nov 2023 08:44:25 GMT
Content-Type: application/json
Content-Length: 403
Connection: close
Server: gunicorn/19.9.0
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true

Response Body:

{
“args”: {},
“data”: “{\”name\”: \”John Doe\”, \”age\”: 30}”,
“files”: {},
“form”: {},
“headers”: {
“Accept”: “/“,
“Accept-Encoding”: “deflate, gzip”,
“Content-Length”: “31”,
“Content-Type”: “application/json”,
“Host”: “httpbin.org”,
“User-Agent”: “PycURL/7.45.1 libcurl/7.81.0 OpenSSL/1.1.1l zlib/1.2.11 brotli/1.0.9 c-ares/1.18.1”,
“X-Amzn-Trace-Id”: “Root=1-65439589-23978c981a8d005a1b5439d5”
},
“json”: {
“age”: 30,
“name”: “John Doe”
},
“origin”: “34.120.134.145”,
“url”: “https://httpbin.org/post”
}

Response Code: 200
“`

httpbin.org 服务会回显我们发送的 POST 数据,从响应体中可以看到,我们成功地发送了 JSON 数据。

4. 使用 PycURL 上传文件

pycurl 还可以用于上传文件。以下是一个示例:

“`python
import pycurl
import io
import os

def upload_file(url, file_path):
“””
使用 pycurl 上传文件并输出响应头和响应体。
“””

buffer = io.BytesIO()

c = pycurl.Curl()
c.setopt(c.URL, url)

# 设置请求类型为 POST
c.setopt(c.POST, 1)

# 设置文件上传
c.setopt(c.HTTPPOST, [('file', (pycurl.FORM_FILE, file_path))])

# 设置 WriteFunction,将响应体写入 buffer
c.setopt(c.WRITEDATA, buffer)

# 设置 HEADERFUNCTION,直接打印响应头
def header_function(header_line):
    print(header_line.decode('utf-8').rstrip())  # 解码并去除尾部换行符
    return len(header_line)

c.setopt(c.HEADERFUNCTION, header_function)


try:
    c.perform()
    body = buffer.getvalue().decode('utf-8')
    print("\nResponse Body:\n")
    print(body)

    # 获取响应状态码
    response_code = c.getinfo(pycurl.RESPONSE_CODE)
    print(f"\nResponse Code: {response_code}")

except pycurl.error as e:
    print(f"An error occurred: {e}")
finally:
    c.close()

if name == ‘main‘:
url = “https://httpbin.org/post” # 使用 httpbin 模拟文件上传
file_path = “example.txt”

# 创建一个示例文件
with open(file_path, "w") as f:
    f.write("This is an example file.")

upload_file(url, file_path)

# 删除示例文件
os.remove(file_path)

“`

代码解释:

  • c.setopt(c.HTTPPOST, [('file', (pycurl.FORM_FILE, file_path))]): 设置文件上传。 HTTPPOST 选项接受一个列表,其中每个元素是一个元组,表示一个表单字段。 第一个元素是字段名,第二个元素是一个元组,包含 pycurl.FORM_FILE 和文件路径。

运行结果:

运行上述代码,你将看到类似以下的输出:

“`
HTTP/1.1 200 OK
Date: Thu, 02 Nov 2023 08:48:35 GMT
Content-Type: application/json
Content-Length: 655
Connection: close
Server: gunicorn/19.9.0
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true

Response Body:

{
“args”: {},
“data”: “”,
“files”: {
“file”: “This is an example file.\n”
},
“form”: {},
“headers”: {
“Accept”: “/“,
“Accept-Encoding”: “deflate, gzip”,
“Content-Length”: “241”,
“Content-Type”: “multipart/form-data; boundary=————————60074a7055120a74”,
“Host”: “httpbin.org”,
“User-Agent”: “PycURL/7.45.1 libcurl/7.81.0 OpenSSL/1.1.1l zlib/1.2.11 brotli/1.0.9 c-ares/1.18.1”,
“X-Amzn-Trace-Id”: “Root=1-6543968b-3e551f810977239d5b51a592”
},
“json”: null,
“origin”: “34.120.134.145”,
“url”: “https://httpbin.org/post”
}

Response Code: 200
“`

从响应体中可以看到,httpbin.org 服务接收到了我们上传的文件内容。

5. 设置 Cookie 和 User-Agent

pycurl 允许我们设置 Cookie 和 User-Agent 等请求头。以下是一个示例:

“`python
import pycurl
import io

def custom_request(url):
“””
使用 pycurl 设置 Cookie 和 User-Agent 并输出响应头和响应体。
“””

buffer = io.BytesIO()

c = pycurl.Curl()
c.setopt(c.URL, url)

# 设置 Cookie
c.setopt(c.COOKIE, "sessionid=1234567890")

# 设置 User-Agent
c.setopt(c.USERAGENT, "My Custom User-Agent")

# 设置 WriteFunction,将响应体写入 buffer
c.setopt(c.WRITEDATA, buffer)

# 设置 HEADERFUNCTION,直接打印响应头
def header_function(header_line):
    print(header_line.decode('utf-8').rstrip())  # 解码并去除尾部换行符
    return len(header_line)

c.setopt(c.HEADERFUNCTION, header_function)

try:
    c.perform()
    body = buffer.getvalue().decode('utf-8')
    print("\nResponse Body:\n")
    print(body)

    # 获取响应状态码
    response_code = c.getinfo(pycurl.RESPONSE_CODE)
    print(f"\nResponse Code: {response_code}")

except pycurl.error as e:
    print(f"An error occurred: {e}")
finally:
    c.close()

if name == ‘main‘:
url = “https://httpbin.org/get” # 使用 httpbin 模拟请求
custom_request(url)
“`

代码解释:

  • c.setopt(c.COOKIE, "sessionid=1234567890"): 设置 Cookie。
  • c.setopt(c.USERAGENT, "My Custom User-Agent"): 设置 User-Agent。

运行结果:

运行上述代码,你将看到类似以下的输出:

“`
HTTP/1.1 200 OK
Date: Thu, 02 Nov 2023 08:52:12 GMT
Content-Type: application/json
Content-Length: 362
Connection: close
Server: gunicorn/19.9.0
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true

Response Body:

{
“args”: {},
“headers”: {
“Accept”: “/“,
“Accept-Encoding”: “deflate, gzip”,
“Cookie”: “sessionid=1234567890”,
“Host”: “httpbin.org”,
“User-Agent”: “My Custom User-Agent”,
“X-Amzn-Trace-Id”: “Root=1-65439774-6824a5b811657c330c321914”
},
“origin”: “34.120.134.145”,
“url”: “https://httpbin.org/get”
}

Response Code: 200
“`

从响应体中可以看到,httpbin.org 服务接收到了我们设置的 Cookie 和 User-Agent。

6. 高级用法和常见问题

  • 处理 SSL 证书验证: 默认情况下,pycurl 会验证 SSL 证书。 如果你需要禁用证书验证(不建议在生产环境中使用),可以使用 c.setopt(c.SSL_VERIFYPEER, 0)c.setopt(c.SSL_VERIFYHOST, 0)
  • 设置超时时间: 可以使用 c.setopt(c.TIMEOUT, seconds) 设置请求的超时时间,单位为秒。
  • 使用代理: 可以使用 c.setopt(c.PROXY, proxy_url) 设置代理服务器。 例如:c.setopt(c.PROXY, "http://127.0.0.1:8080")
  • 处理重定向: 可以使用 c.setopt(c.FOLLOWLOCATION, 1) 自动跟随重定向。
  • 编码问题: 确保正确处理编码问题。 默认情况下,pycurl 返回的是字节串,需要根据服务器返回的 Content-Type 头进行解码。

总结

pycurl 是一个功能强大的 Python 库,它提供了对 libcurl 的底层访问,允许我们进行各种复杂的 HTTP 请求。 通过本文的示例,你应该掌握了如何使用 pycurl 发送 GET 和 POST 请求,上传文件,设置 Cookie 和 User-Agent,以及直接输出请求结果(包括响应头和响应体)。 虽然 pycurl 的使用可能比 requests 库略微复杂,但它提供了更大的灵活性和控制力,适用于需要精细控制网络请求的场景。 记住,安全至关重要,在生产环境中应避免禁用 SSL 证书验证,并仔细处理用户输入以防止安全漏洞。 通过不断实践和学习,你将能够充分利用 pycurl 的强大功能,解决各种网络编程问题。

发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注

滚动至顶部