Python requests 设置自定义头部教程

PythonBeginner
立即练习

介绍

在 Web 开发和数据检索的世界里,理解如何在 Python requests 中设置自定义头部(custom headers)是一项至关重要的技能。本教程将指导你如何向你的 Python requests 添加自定义头部,从而开启 Web 抓取、API 交互等更广泛的可能性。

自定义头部允许你控制 Web 服务器和 API 处理你的请求的方式。它们可以帮助你验证请求、指定内容类型、管理缓存,甚至模拟浏览器行为。在本教程结束时,你将掌握实用的知识,能够自定义你的 HTTP 请求以满足特定需求。

理解 HTTP 头部和 Requests 库

在开始编写代码之前,让我们先了解一下 HTTP 头部是什么以及它们为什么重要。

什么是 HTTP 头部?

HTTP 头部是在客户端和服务器之间发送的请求和响应中的键值对。它们提供了关于请求或响应的额外信息,例如内容类型、身份验证凭据或客户端信息。

例如,当你访问一个网站时,你的浏览器会自动包含像 User-Agent(标识你的浏览器)、Accept(指定你可以处理的内容类型)等头部。

安装 Requests 库

Python 的 Requests 库使处理 HTTP 请求变得简单。让我们确保它已安装在我们的环境中:

  1. 在 WebIDE 中打开一个终端并运行:
pip install requests

你应该看到输出,表明 requests 正在安装或已经安装:

Requirement already satisfied: requests in /usr/local/lib/python3.10/dist-packages (2.28.1)
...

使用 Requests 创建你的第一个 Python 脚本

让我们创建一个简单的 Python 脚本来测试 requests 库:

  1. 点击 WebIDE 左侧边栏中的 Explorer 图标
  2. 在文件资源管理器中右键单击并选择“New File”
  3. 将文件命名为 test_requests.py
  4. 将以下代码添加到文件中:
import requests

## Make a simple GET request to a test website
response = requests.get('https://httpbin.org/get')

## Print the response status code
print(f"Status Code: {response.status_code}")

## Print the response headers (what the server sent back)
print("\nResponse Headers:")
for header, value in response.headers.items():
    print(f"{header}: {value}")

## Print the response content
print("\nResponse Content:")
print(response.text[:300] + "...")  ## Showing just the first 300 characters
  1. 通过打开一个终端并执行以下命令来运行脚本:
python test_requests.py

你应该看到类似于以下的输出:

Status Code: 200

Response Headers:
Date: Wed, 12 Apr 2023 10:15:23 GMT
Content-Type: application/json
Content-Length: 267
Server: gunicorn/19.9.0
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true

Response Content:
{
  "args": {},
  "headers": {
    "Accept": "*/*",
    "Accept-Encoding": "gzip, deflate",
    "Host": "httpbin.org",
    "User-Agent": "python-requests/2.28.1",
    "X-Amzn-Trace-Id": "Root=1-643..."
  },
  "origin": "123.45.67.89",
  "url": "https://httpbin.org/get"
}
...

此输出显示:

  1. 服务器响应的状态码为 200(成功)
  2. 服务器发回的头部
  3. 响应的实际内容(JSON 格式)

请注意,服务器记录了它从我们这里收到的头部,包括自动生成的 User-Agent 头部,该头部标识我们的请求来自 Python requests 库。

在下一步中,我们将学习如何自定义这些头部,以便更好地控制我们的请求。

在 Python Requests 中设置基本的自定义头部

现在我们已经了解了什么是 HTTP 头部,并且测试了 requests 库,让我们学习如何在我们的请求中设置自定义头部。

为什么设置自定义头部?

设置自定义头部有几个原因:

  1. 身份验证(Authentication):许多 API 需要在头部发送身份验证令牌
  2. User-Agent:更改你向网站标识自己的方式
  3. Content-Type:指定你正在发送的数据的格式
  4. Accept:指示你可以处理的内容类型
  5. 自定义头部(Custom Headers):某些 API 需要特定的自定义头部

在 Requests 中设置头部

让我们创建一个新的 Python 脚本来练习设置自定义头部:

  1. 在 WebIDE 中,创建一个名为 custom_headers.py 的新文件
  2. 添加以下代码:
import requests

## Define the URL we'll make the request to
url = 'https://httpbin.org/headers'

## Define custom headers in a dictionary
custom_headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
    'X-Custom-Header': 'Hello World',
    'Accept-Language': 'en-US,en;q=0.9'
}

## Make the request with our custom headers
response = requests.get(url, headers=custom_headers)

## Print the status code
print(f"Status Code: {response.status_code}")

## Print the response content (which shows the headers the server received)
print("\nHeaders received by server:")
print(response.json())
  1. 运行脚本:
python custom_headers.py

你应该看到类似于以下的输出:

Status Code: 200

Headers received by server:
{'headers': {'Accept': '*/*', 'Accept-Encoding': 'gzip, deflate', 'Accept-Language': 'en-US,en;q=0.9', 'Host': 'httpbin.org', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36', 'X-Custom-Header': 'Hello World', 'X-Amzn-Trace-Id': 'Root=1-6430a123-abc123def456'}}

发生了什么?

在这个脚本中,我们:

  1. 创建了一个名为 custom_headers 的字典,其中包含三个头部:

    • User-Agent:我们将其从默认的 Python requests 值更改为模拟 Web 浏览器
    • X-Custom-Header:我们发明的完全自定义的头部
    • Accept-Language:指定内容的首选语言
  2. 使用 headers 参数将我们的头部传递给 requests.get()

  3. 来自 httpbin.org/headers 的响应向我们显示了收到了哪些头部,确认了我们的自定义头部已成功发送

为特定用例修改头部

让我们创建另一个例子,我们假装自己是一个移动设备。这在测试移动端响应式网站时非常有用:

  1. 创建一个名为 mobile_headers.py 的新文件
  2. 添加以下代码:
import requests

url = 'https://httpbin.org/headers'

## Header to simulate an iPhone
mobile_headers = {
    'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.0 Mobile/15E148 Safari/604.1',
    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8'
}

print("Making request with mobile device headers...")
response = requests.get(url, headers=mobile_headers)

## Print the response content
print(response.json())
  1. 运行脚本:
python mobile_headers.py

你应该看到类似于以下的输出:

Making request with mobile device headers...
{'headers': {'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', 'Accept-Encoding': 'gzip, deflate', 'Host': 'httpbin.org', 'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.0 Mobile/15E148 Safari/604.1', 'X-Amzn-Trace-Id': 'Root=1-6430a456-abc123def456'}}

这表明我们通过设置特定的 User-Agent 头部,成功地告诉服务器我们是一部 iPhone。

使用身份验证头部

自定义头部最常见的用途之一是与 Web 服务和 API 进行身份验证。许多 API 要求你在请求头部中包含身份验证信息。

理解身份验证头部

有几种常见的身份验证方法:

  1. API 密钥(API Keys):包含在头部或 URL 参数中的简单令牌
  2. 基本身份验证(Basic Authentication):Base64 编码的用户名和密码
  3. 持有者令牌(Bearer Tokens):用于 OAuth 和 JWT 身份验证
  4. 自定义身份验证(Custom Authentication):专有的身份验证方案

让我们探讨如何使用 Python requests 实现这些身份验证方法。

API 密钥身份验证

许多 API 允许使用 API 密钥进行访问。这些通常包含在头部或作为 URL 参数:

  1. 创建一个名为 api_key_auth.py 的新文件
  2. 添加以下代码:
import requests

url = 'https://httpbin.org/headers'

## Simulating an API key authentication
api_key = 'my_fake_api_key_12345'

## Add the API key to the headers
headers = {
    'X-API-Key': api_key,
    'User-Agent': 'My API Client/1.0'
}

## Make the request
response = requests.get(url, headers=headers)

## Print results
print(f"Status Code: {response.status_code}")
print("\nHeaders received by server:")
print(response.json())
  1. 运行脚本:
python api_key_auth.py

你应该看到类似于以下的输出:

Status Code: 200

Headers received by server:
{'headers': {'Accept': '*/*', 'Accept-Encoding': 'gzip, deflate', 'Host': 'httpbin.org', 'User-Agent': 'My API Client/1.0', 'X-API-Key': 'my_fake_api_key_12345', 'X-Amzn-Trace-Id': 'Root=1-6430a789-abc123def456'}}

这确认我们已成功在 X-API-Key 头部中发送了 API 密钥。

基本身份验证

基本身份验证涉及发送以 base64 格式编码的用户名和密码。Requests 库使这变得容易:

  1. 创建一个名为 basic_auth.py 的新文件
  2. 添加以下代码:
import requests

## URL that requires basic authentication
url = 'https://httpbin.org/basic-auth/user/pass'

## Method 1: Using the auth parameter (recommended)
print("Method 1: Using the auth parameter")
response = requests.get(url, auth=('user', 'pass'))
print(f"Status Code: {response.status_code}")
print(response.json())

## Method 2: Setting the Authorization header manually
print("\nMethod 2: Setting the Authorization header manually")
import base64

## Create the basic auth string: "username:password" encoded in base64
auth_string = base64.b64encode('user:pass'.encode('utf-8')).decode('utf-8')
headers = {
    'Authorization': f'Basic {auth_string}'
}

response = requests.get(url, headers=headers)
print(f"Status Code: {response.status_code}")
print(response.json())
  1. 运行脚本:
python basic_auth.py

你应该看到类似于以下的输出:

Method 1: Using the auth parameter
Status Code: 200
{'authenticated': True, 'user': 'user'}

Method 2: Setting the Authorization header manually
Status Code: 200
{'authenticated': True, 'user': 'user'}

这两种方法都成功地通过了服务的身份验证:

  • 方法 1 使用内置的 auth 参数,这更方便
  • 方法 2 通过手动创建 Authorization 头部,展示了基本身份验证“幕后”的工作方式

持有者令牌身份验证

持有者令牌身份验证通常用于 OAuth 2.0 和基于 JWT 的系统:

  1. 创建一个名为 bearer_auth.py 的新文件
  2. 添加以下代码:
import requests

url = 'https://httpbin.org/headers'

## Simulate a bearer token (in a real app this would come from an OAuth process)
bearer_token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIn0.Q6CM1qIQkXA_DqyJq9MI0-mnRRCRR3c0SIM-Nul5MZs'

## Add the Authorization header with the Bearer token
headers = {
    'Authorization': f'Bearer {bearer_token}'
}

## Make the request
response = requests.get(url, headers=headers)

## Print results
print(f"Status Code: {response.status_code}")
print("\nHeaders received by server:")
print(response.json())
  1. 运行脚本:
python bearer_auth.py

你应该看到类似于以下的输出:

Status Code: 200

Headers received by server:
{'headers': {'Accept': '*/*', 'Accept-Encoding': 'gzip, deflate', 'Authorization': 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIn0.Q6CM1qIQkXA_DqyJq9MI0-mnRRCRR3c0SIM-Nul5MZs', 'Host': 'httpbin.org', 'X-Amzn-Trace-Id': 'Root=1-6430a901-abc123def456'}}

这显示了在 Authorization 头部中包含持有者令牌的成功请求。

持有者令牌通常在通过 OAuth 2.0 服务器成功完成身份验证过程后获得,但在本例中,我们使用一个示例令牌进行演示。

实际应用和最佳实践

现在你已经学会了如何设置各种类型的自定义头部,让我们探讨一些在实际场景中使用头部的实际应用和最佳实践。

发送和接收 JSON 数据

在使用现代 API 时,JSON 是最常见的数据格式。让我们看看如何为 JSON 请求正确设置头部:

  1. 创建一个名为 json_requests.py 的新文件
  2. 添加以下代码:
import requests
import json

url = 'https://httpbin.org/post'  ## This endpoint accepts POST requests

## Data to send
data = {
    'name': 'John Doe',
    'email': 'john@example.com',
    'message': 'Hello, world!'
}

## Set appropriate headers for JSON
headers = {
    'Content-Type': 'application/json',
    'Accept': 'application/json'
}

## Method 1: Using the json parameter (recommended)
print("Method 1: Using the json parameter")
response = requests.post(url, json=data, headers=headers)
print(f"Status Code: {response.status_code}")
print(response.json()['headers'])  ## Show the headers received
print(f"\nData sent (as received by server): {response.json()['json']}")

## Method 2: Manually converting to JSON
print("\nMethod 2: Manually converting to JSON")
json_data = json.dumps(data)
response = requests.post(url, data=json_data, headers=headers)
print(f"Status Code: {response.status_code}")
print(response.json()['headers'])  ## Show the headers received
print(f"\nData sent (as received by server): {response.json()['json']}")
  1. 运行脚本:
python json_requests.py

你应该看到类似于以下的输出:

Method 1: Using the json parameter
Status Code: 200
{'Accept': 'application/json', 'Accept-Encoding': 'gzip, deflate', 'Content-Length': '72', 'Content-Type': 'application/json', 'Host': 'httpbin.org', 'X-Amzn-Trace-Id': 'Root=1-6430ab12-abc123def456'}

Data sent (as received by server): {'name': 'John Doe', 'email': 'john@example.com', 'message': 'Hello, world!'}

Method 2: Manually converting to JSON
Status Code: 200
{'Accept': 'application/json', 'Accept-Encoding': 'gzip, deflate', 'Content-Length': '72', 'Content-Type': 'application/json', 'Host': 'httpbin.org', 'X-Amzn-Trace-Id': 'Root=1-6430ab13-abc123def456'}

Data sent (as received by server): {'name': 'John Doe', 'email': 'john@example.com', 'message': 'Hello, world!'}

请注意,这两种方法都有效,但方法 1 更方便,因为 Requests 库为你处理了 JSON 转换。

使用默认头部创建可重用的会话(Session)

如果你需要使用相同的头部进行多个请求,使用 Session 对象可以节省时间并使你的代码更简洁:

  1. 创建一个名为 session_headers.py 的新文件
  2. 添加以下代码:
import requests

## Create a session object
session = requests.Session()

## Set default headers for all requests made with this session
session.headers.update({
    'User-Agent': 'MyCustomApp/1.0',
    'Accept-Language': 'en-US,en;q=0.9',
    'X-API-Key': 'my_session_api_key'
})

## Make a request using the session - it will include our default headers
print("First request with session:")
response = session.get('https://httpbin.org/headers')
print(response.json())

## Add a custom header just for this request
print("\nSecond request with additional header:")
response = session.get('https://httpbin.org/headers',
                      headers={'X-Custom-Header': 'Just for this request'})
print(response.json())

## Original headers remain unchanged for future requests
print("\nThird request (original headers only):")
response = session.get('https://httpbin.org/headers')
print(response.json())
  1. 运行脚本:
python session_headers.py

你应该看到类似于以下的输出:

First request with session:
{'headers': {'Accept': '*/*', 'Accept-Encoding': 'gzip, deflate', 'Accept-Language': 'en-US,en;q=0.9', 'Host': 'httpbin.org', 'User-Agent': 'MyCustomApp/1.0', 'X-API-Key': 'my_session_api_key', 'X-Amzn-Trace-Id': 'Root=1-6430ab45-abc123def456'}}

Second request with additional header:
{'headers': {'Accept': '*/*', 'Accept-Encoding': 'gzip, deflate', 'Accept-Language': 'en-US,en;q=0.9', 'Host': 'httpbin.org', 'User-Agent': 'MyCustomApp/1.0', 'X-API-Key': 'my_session_api_key', 'X-Custom-Header': 'Just for this request', 'X-Amzn-Trace-Id': 'Root=1-6430ab46-abc123def456'}}

Third request (original headers only):
{'headers': {'Accept': '*/*', 'Accept-Encoding': 'gzip, deflate', 'Accept-Language': 'en-US,en;q=0.9', 'Host': 'httpbin.org', 'User-Agent': 'MyCustomApp/1.0', 'X-API-Key': 'my_session_api_key', 'X-Amzn-Trace-Id': 'Root=1-6430ab47-abc123def456'}}

使用会话是最佳实践,原因如下:

  1. 提高性能(连接池)
  2. 跨请求的头部一致性
  3. 自动处理 Cookie
  4. 根据需要添加每个请求的自定义

使用头部的最佳实践

总而言之,以下是在使用 HTTP 头部时要遵循的一些最佳实践:

  1. 对于对同一域名的多个请求,使用 Session 对象
  2. 为你要发送的数据正确设置 Content-Type 头部
  3. 正确处理身份验证 - 尽可能使用内置的身份验证
  4. 保护敏感信息 - 不要对 API 密钥或令牌进行硬编码
  5. 仔细遵循 API 文档,了解所需的头部

这是一个演示这些最佳实践的最终示例:

  1. 创建一个名为 best_practices.py 的新文件
  2. 添加以下代码:
import requests
import os

## In a real application, get these from environment variables or a secure configuration
## For this example, we're keeping it simple
API_KEY = os.environ.get('API_KEY', 'default_api_key')
BASE_URL = 'https://httpbin.org'

def create_api_client():
    """Create a reusable session with default headers."""
    session = requests.Session()

    ## Set common headers
    session.headers.update({
        'User-Agent': 'MyApp/1.0',
        'X-API-Key': API_KEY,
        'Accept': 'application/json'
    })

    return session

def get_data(client, endpoint):
    """Make a GET request to the specified endpoint."""
    url = f"{BASE_URL}/{endpoint}"
    response = client.get(url)
    return response.json()

def post_data(client, endpoint, data):
    """Make a POST request with JSON data."""
    url = f"{BASE_URL}/{endpoint}"
    response = client.post(url, json=data)
    return response.json()

## Usage example
def main():
    ## Create the API client
    client = create_api_client()

    ## GET request example
    print("Making GET request...")
    get_response = get_data(client, 'headers')
    print(f"Headers sent: {get_response['headers']}")

    ## POST request example
    print("\nMaking POST request...")
    data = {'name': 'John', 'age': 30}
    post_response = post_data(client, 'post', data)
    print(f"Data received by server: {post_response['json']}")

if __name__ == '__main__':
    main()
  1. 运行脚本:
python best_practices.py

你应该看到类似于以下的输出:

Making GET request...
Headers sent: {'Accept': 'application/json', 'Accept-Encoding': 'gzip, deflate', 'Host': 'httpbin.org', 'User-Agent': 'MyApp/1.0', 'X-API-Key': 'default_api_key', 'X-Amzn-Trace-Id': 'Root=1-6430ab78-abc123def456'}

Making POST request...
Data received by server: {'name': 'John', 'age': 30}

此示例演示了一种使用自定义头部进行 HTTP 请求的结构化方法,遵循最佳实践,例如创建可重用的会话,将代码组织成函数,以及避免对敏感信息进行硬编码。

总结

在本教程中,你学习了如何在 Python requests 中使用自定义头部,这是进行有效 Web 通信和 API 集成的必备技能。

你现在了解:

  • 什么是 HTTP 头部以及它们为什么对 Web 请求很重要
  • 如何为单个请求设置自定义头部
  • 使用头部的各种身份验证方法(API 密钥、基本身份验证、持有者令牌)
  • 如何正确处理 JSON 数据和内容类型头部
  • 使用会话对象管理头部的最佳实践

这些技能将使你能够更有效地与任何 Web API 交互,访问受保护的资源,控制你的请求的处理方式,并构建更复杂的 Web 应用程序。

在你继续发展你的 Python 技能时,请记住,理解 HTTP 基础知识,如头部、状态码和内容类型,将帮助你解决问题并在你的 Web 应用程序中实现更高级的功能。