杰瑞科技汇

Python webservice调用时如何处理跨域与鉴权?

目录

  1. WebService 基础概念
    • 什么是 WebService?
    • 主要协议:SOAP vs. REST
  2. 调用 RESTful WebService (最常用)
    • 使用 requests
    • 示例:GET 请求和 POST 请求
    • 处理响应(JSON)
  3. 调用 SOAP WebService
    • 使用 zeep
    • 示例:连接 WSDL 并调用方法
  4. 调用其他类型的 API
    • XML-RPC (使用 xmlrpc.client)
  5. 高级主题与最佳实践
    • 异常处理
    • 会话管理
    • 超时设置
    • 认证(API Key, OAuth)
  6. 总结与如何选择

WebService 基础概念

什么是 WebService?

WebService 是一种通过网络进行应用程序间通信的技术,它允许不同平台、不同语言的应用程序通过标准的 Web 协议(如 HTTP/HTTPS)进行数据交换,你可以把它想象成一个“远程函数”,你的程序可以调用它,并获取返回结果,而不需要关心它具体是如何实现的。

Python webservice调用时如何处理跨域与鉴权?-图1
(图片来源网络,侵删)

主要协议:SOAP vs. REST

这是理解如何调用 WebService 的关键。

特性 SOAP (Simple Object Access Protocol) REST (Representational State Transfer)
协议 严格的协议,基于 XML,消息格式是固定的 SOAP Envelope。 一种架构风格,没有严格的协议,通常基于 HTTP。
数据格式 严格要求使用 XML。 非常灵活,常用 JSON、XML、HTML、纯文本等,JSON 因其轻量级而最受欢迎。
标准 有很多标准,如 WS-Security (安全)、WS-Addressing (寻址)等,功能强大。 没有官方标准,依赖于 HTTP 标准 (GET, POST, PUT, DELETE)。
性能 XML 格式冗长,解析开销大,性能相对较低。 数据格式轻量(尤其是 JSON),传输快,性能高。
使用场景 企业级应用、金融、电信等对安全性、事务性要求高的场景。 公共 API、移动应用后端、微服务等绝大多数现代 Web 应用。

REST API 是绝对的主流,绝大多数新的 WebService 都采用 REST 风格,SOAP 则多用于遗留系统或特定行业,掌握 requests 调用 REST API 是最重要的。


调用 RESTful WebService (使用 requests 库)

requests 是 Python 中最著名、最易用的 HTTP 库,没有之一,它是调用 REST API 的首选。

安装 requests

pip install requests

示例 1:GET 请求(获取数据)

假设我们要调用一个公共的天气 API(这里使用 jsonplaceholder 作为示例,它是一个免费的在线测试 API)。

Python webservice调用时如何处理跨域与鉴权?-图2
(图片来源网络,侵删)
import requests
import json # 用于美化打印 JSON
# API 的 URL
url = "https://jsonplaceholder.typicode.com/posts/1"
try:
    # 发送 GET 请求
    # timeout 参数非常重要,可以防止程序因网络问题而无限期挂起
    response = requests.get(url, timeout=10)
    # 检查请求是否成功 (状态码 200-299 表示成功)
    response.raise_for_status() 
    # 获取响应内容,并解析为 Python 字典
    # response.json() 会自动将 JSON 响应内容转换为 Python 对象
    data = response.json()
    # 打印获取到的数据
    print("请求成功!")
    print("响应数据 (JSON 格式):")
    print(json.dumps(data, indent=4, ensure_ascii=False))
    # 访问特定的数据
    print(f"\n用户 ID: {data['userId']}")
    print(f"标题: {data['title']}")
except requests.exceptions.HTTPError as http_err:
    print(f"HTTP 错误发生: {http_err}")
except requests.exceptions.ConnectionError as conn_err:
    print(f"连接错误发生: {conn_err}")
except requests.exceptions.Timeout as timeout_err:
    print(f"请求超时: {timeout_err}")
except requests.exceptions.RequestException as err:
    print(f"发生了一个未知错误: {err}")

示例 2:POST 请求(发送数据)

import requests
import json
# API 的 URL
url = "https://jsonplaceholder.typicode.com/posts"
# 要发送的数据 (一个 Python 字典)
payload = {: 'foo',
    'body': 'bar',
    'userId': 1
}
# 请求头,告诉服务器我们发送的是 JSON 数据
headers = {
    'Content-Type': 'application/json; charset=UTF-8'
}
try:
    # 发送 POST 请求
    # data=json.dumps(payload) 将 Python 字典转换为 JSON 字符串
    response = requests.post(url, data=json.dumps(payload), headers=headers, timeout=10)
    # 检查请求是否成功
    response.raise_for_status()
    # 获取服务器返回的创建的资源数据
    created_data = response.json()
    print("POST 请求成功!")
    print("服务器返回的新创建的数据:")
    print(json.dumps(created_data, indent=4, ensure_ascii=False))
except requests.exceptions.RequestException as err:
    print(f"发生了一个错误: {err}")

调用 SOAP WebService (使用 zeep 库)

SOAP 服务通常通过一个 WSDL (Web Services Description Language) 文件来描述其接口,WSDL 文件定义了可用的方法、参数和返回值的结构。

安装 zeep

pip install zeep

示例:调用一个公共的 SOAP WebService

这里我们使用 ws.cdyne.com 提供的天气查询服务作为示例。

from zeep import Client
from zeep.transports import Transport
from requests import Session
# WSDL 文件的 URL
wsdl_url = "http://wsf.cdyne.com/WeatherWS/Weather.asmx?wsdl"
try:
    # (可选) 设置超时
    session = Session()
    session.timeout = 10  # 超时时间,单位:秒
    transport = Transport(session=session)
    # 创建 zeep 客户端
    # wsdl 参数指定 WSDL 地址
    # transport 参数用于自定义传输层,如设置超时
    client = Client(wsdl=wsdl_url, transport=transport)
    # 查看服务提供的方法
    print("可用的服务端口:")
    print(client.wsdl.services)
    print("\n可用的操作:")
    print(client.wsdl.services['WeatherSoap']['WeatherSoap'].ports)
    # 调用 WSDL 中定义的方法
    # 方法名可以直接通过客户端对象访问
    # 参数名必须与 WSDL 中定义的一致
    response = client.service.GetCityWeatherByZIP('10001') # 使用纽约的邮编
    # 打印响应结果
    # SOAP 响应通常是一个复杂对象,zeep 会将其转换为 Python 的字典或对象
    print("\nSOAP 响应结果:")
    if response.Success:
        print(f"城市: {response.City}")
        print(f"状态: {response.State}")
        print(f"温度: {response.Temperature}°F")
        print(f"描述: {response.Description}")
    else:
        print(f"查询失败: {response.ResponseText}")
except Exception as e:
    print(f"调用 SOAP 服务时发生错误: {e}")

调用其他类型的 API (XML-RPC)

XML-RPC 是一种更简单的远程过程调用协议,使用 XML 编码数据,通过 HTTP 传输,Python 标准库就包含了 xmlrpc.client 模块。

import xmlrpc.client
# API 的 URL
server_url = "https://requestbin.net/r/your-dump-bin-id" # 注意:这是一个示例,你需要一个真实的 XML-RPC 服务器
try:
    # 创建代理
    proxy = xmlrpc.client.ServerProxy(server_url)
    # 调用服务器上的方法
    # 假设服务器有一个名为 'add' 的方法
    result = proxy.add(2, 3)
    print(f"调用 add(2, 3) 的结果是: {result}")
    # 调用另一个方法,'listMethods'
    methods = proxy.system.listMethods()
    print(f"服务器支持的方法列表: {methods}")
except xmlrpc.client.Fault as err:
    print("一个 XML-RPC 错误发生:")
    print(f"Fault code: {err.faultCode}")
    print(f"Fault string: {err.faultString}")
except OSError as err:
    print(f"网络错误发生: {err}")
except Exception as e:
    print(f"发生了一个未知错误: {e}")

高级主题与最佳实践

异常处理

网络调用是不可靠的,必须处理各种异常:

Python webservice调用时如何处理跨域与鉴权?-图3
(图片来源网络,侵删)
  • requests.exceptions.RequestException: requests 库中所有异常的基类。
  • requests.exceptions.HTTPError: HTTP 错误 (4xx, 5xx)。
  • requests.exceptions.ConnectionError: 网络连接问题。
  • requests.exceptions.Timeout: 请求超时。
  • zeep.exceptions.Fault: SOAP 调用中的错误。

会话管理 (requests.Session)

如果你需要向同一个域名的多个接口发送请求,使用 Session 对象可以复用 TCP 连接,提高性能,并可以统一设置 cookies 或 headers。

import requests
# 创建一个会话对象
with requests.Session() as session:
    # 设置会话级别的 headers
    session.headers.update({'User-Agent': 'MyPythonApp/1.0'})
    # 第一次请求
    response1 = session.get('https://httpbin.org/cookies/set/testname/testvalue')
    print("第一次请求后的 Cookies:", response1.cookies.get_dict())
    # 第二次请求会自动带上第一次设置的 cookies
    response2 = session.get('https://httpbin.org/cookies')
    print("第二次请求获取到的 Cookies:", response2.json())

超时设置

timeout 参数至关重要,它可以防止你的程序因网络延迟或服务器无响应而卡死。

  • requests.get(url, timeout=5): 5秒后连接超时。
  • requests.get(url, timeout=(3.05, 27)): 3.05秒后连接超时,27秒后读取超时。

认证

许多 WebService 需要认证。

  • API Key (最常见):

    api_key = "YOUR_API_KEY"
    headers = {'Authorization': f'Bearer {api_key}'}
    response = requests.get('https://api.example.com/data', headers=headers)
  • Basic Auth (用户名/密码):

    from requests.auth import HTTPBasicAuth
    response = requests.get('https://api.example.com/data', auth=HTTPBasicAuth('username', 'password'))
    # 或者更简单
    response = requests.get('https://api.example.com/data', auth=('username', 'password'))
  • OAuth 2.0 (复杂): 通常需要使用专门的库如 requests-oauthlib 来处理授权流程。


总结与如何选择

场景 推荐库/方法 理由
调用现代 REST API requests 事实上的标准,简单、强大、文档齐全、社区活跃。
调用传统 SOAP WebService zeep 自动解析 WSDL,将 SOAP 操作映射为 Python 方法,使用极其方便。
调用内部 XML-RPC 服务 xmlrpc.client Python 标准库,无需安装,适用于遗留系统。
需要高性能或异步调用 httpx, aiohttp httpxrequests 的现代替代品,支持同步和异步。aiohttp 是专门为异步设计的。
需要生成客户端代码 wsdl2py (SOAP) 对于复杂的 SOAP 服务,可以先从 WSDL 生成 Python 客户端代码,简化调用。

最终建议:

  1. 首选 requests:超过 90% 的情况下,你都会用到它,它是 Python Web 开发的必备技能。
  2. 明确服务类型:在调用前,务必确认目标 WebService 是 REST 还是 SOAP,查看其文档,寻找 URL 是 .../api/resource (REST) 还是 ...?wsdl (SOAP)。
  3. 仔细阅读文档:每个 API 都有其特定的规则,包括认证方式、请求/响应格式、参数名称等,官方文档是最好的参考资料。
分享:
扫描分享到社交APP
上一篇
下一篇