杰瑞科技汇

Python如何调用WebService?

  1. 基于 SOAP (Simple Object Access Protocol):这是一种比较传统的、基于 XML 的协议,通常有 WSDL (Web Services Description Language) 文件来描述服务的接口。
  2. 基于 REST (Representational State Transfer):这是目前更流行、更轻量级的架构,通常通过 HTTP/HTTPS 协议,以 JSON 或 XML 格式传输数据,它没有 WSDL,而是通过 API 文档(如 Swagger/OpenAPI)来描述接口。

下面我将分别介绍如何使用 Python 调用这两种类型的 WebService。

Python如何调用WebService?-图1
(图片来源网络,侵删)

调用基于 SOAP 的 WebService

调用 SOAP 服务最关键的是拿到服务的 WSDL 文件地址,WSDL 文件就像是服务的“说明书”,定义了所有可用的方法、参数和返回值的结构。

我们将使用 zeep 这个强大的第三方库,它能自动解析 WSDL 并生成 Python 方法,让我们可以像调用本地函数一样调用远程服务。

安装 zeep

pip install zeep

示例:调用一个天气预报的 SOAP 服务

这里我们使用一个公共的测试服务:http://wsf.cdyne.com/WeatherWS/Weather.asmx?wsdl

这个服务有一个方法 GetCityWeatherByZIP,可以通过邮编获取城市天气。

Python如何调用WebService?-图2
(图片来源网络,侵删)

Python 代码实现

from zeep import Client
# WSDL 文件的地址
wsdl_url = 'http://wsf.cdyne.com/WeatherWS/Weather.asmx?wsdl'
try:
    # 1. 创建客户端,zeep 会自动下载并解析 WSDL 文件
    client = Client(wsdl_url)
    print("成功连接到 WebService,WSDL 信息如下:")
    # print(client.wsdl) # 打印 WSDL 的详细信息,可以看看里面有什么
    # 2. 准备调用服务所需的参数
    # 参数名需要和 WSDL 中定义的参数名一致
    # 你可以通过 client.service.GetCityWeatherByZIP() 来查看需要哪些参数
    zip_code = '90210'  # 比如比弗利山庄的邮编
    # 3. 调用服务方法
    # client.service.GetCityWeatherByZIP 会根据 WSDL 自动生成
    # 参数可以直接以关键字参数的形式传入
    result = client.service.GetCityWeatherByZIP(ZIP=zip_code)
    # 4. 处理返回结果
    # 返回结果也是一个 Python 对象,其属性对应 SOAP 响应中的 XML 节点
    if result.Success:
        print("\n成功获取天气信息:")
        print(f"城市: {result.City}")
        print(f"省份: {result.State}")
        print(f"温度: {result.Temperature}°F")
        print(f"天气状况: {result.Description}")
    else:
        print(f"\n获取天气失败: {result.ResponseText}")
except Exception as e:
    print(f"调用 WebService 时发生错误: {e}")

代码解析:

  1. Client(wsdl_url)zeep 的核心,它会从 WSDL 地址获取服务描述,并创建一个客户端对象。
  2. client.service:通过 client.service 可以访问到 WSDL 中定义的所有服务方法。
  3. 参数传递:方法参数的名字需要和 WSDL 中定义的 <part> 元素的 name 属性一致。zeep 非常智能,你可以直接使用 Python 的关键字参数。
  4. 返回结果:返回的结果被自动转换成了 Python 的对象(字典或自定义类),你可以通过 操作符直接访问其属性,非常方便。

调用基于 REST 的 WebService

RESTful WebService 本质上就是一些特定的 URL 端点,我们通过向这些 URL 发送 HTTP 请求(GET, POST, PUT, DELETE 等)并传递参数(通常在 URL、Header 或 Body 中)来与服务器交互,然后接收 JSON 或 XML 格式的响应。

Python 内置的 requests 库是调用 REST API 的首选工具。

requests 库简介

requests 库让 HTTP 请求变得异常简单。

Python如何调用WebService?-图3
(图片来源网络,侵删)
  • requests.get(url, params=None, headers=None, json=None): 发送 GET 请求。
  • requests.post(url, data=None, json=None, headers=None): 发送 POST 请求。
  • requests.put(...), requests.delete(...) 等。

示例:调用一个公共的 JSONPlaceholder REST API

我们将使用 JSONPlaceholder,这是一个免费的在线 REST API 测试服务。

我们将实现一个常见的操作:获取一个用户的所有文章列表

API 端点是:https://jsonplaceholder.typicode.com/posts?userId=1

Python 代码实现

import requests
import json
# REST API 的 URL
# 获取 ID 为 1 的用户的所有文章
api_url = 'https://jsonplaceholder.typicode.com/posts'
try:
    # 1. 准备请求参数
    # 我们想获取 userId=1 的文章,params 是一个字典
    params = {
        'userId': 1
    }
    # 2. 发送 GET 请求
    # requests.get 会自动将 params 字典拼接到 URL 后面
    # headers 可以用来设置 Content-Type, Authorization 等
    response = requests.get(api_url, params=params)
    # 3. 检查请求是否成功
    # response.raise_for_status() 会在请求失败 (状态码 4xx or 5xx) 时抛出异常
    response.raise_for_status()
    # 4. 解析响应内容
    # response.text 是原始的字符串内容
    # response.json() 会自动将 JSON 字符串解析成 Python 的列表或字典
    posts = response.json()
    # 5. 处理数据
    print(f"成功获取到 {len(posts)} 篇文章:\n")
    for i, post in enumerate(posts):
        print(f"--- 文章 {i+1} ---")
        print(f"ID: {post['id']}")
        print(f"标题: {post['title']}")
        print(f"内容: {post['body'][:50]}...") # 只打印内容前50个字符
        print("-" * 20)
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}")
except json.JSONDecodeError:
    print("响应内容不是有效的 JSON 格式")

代码解析:

  1. requests.get(api_url, params=params):发送 GET 请求。params 参数会被 requests 自动编码并附加到 URL 后面,变成 .../posts?userId=1
  2. response.raise_for_status():这是一个非常好的习惯,它会检查 HTTP 状态码,如果状态码表示失败(如 404 Not Found, 500 Server Error),它会抛出 HTTPError 异常。
  3. response.json():这是处理 JSON 响应的利器,它将 JSON 文本直接转换为 Python 的原生数据结构(字典或列表),极大简化了后续的数据处理。
  4. 异常处理:网络请求充满了不确定性(服务器宕机、网络中断、API 变更等),因此健壮的代码必须包含异常处理。

总结与对比

特性 SOAP (使用 zeep) REST (使用 requests)
协议 基于 XML,有自己的规范(SOAP envelope, header, body)。 基于标准的 HTTP/HTTPS 协议。
描述语言 WSDL (Web Services Description Language),非常详细地描述了接口。 无标准描述语言,通常使用 Swagger/OpenAPI 文档。
数据格式 通常是 XML。 通常是 JSON,也可以是 XML、纯文本等。
调用方式 类似 RPC(远程过程调用),有明确的“方法”概念。 基于资源(URI)和 HTTP 动词(GET, POST, PUT, DELETE)。
Python 库 zeep, suds-py3 requests (事实上的标准)
适用场景 企业级应用、金融、电信等对协议规范和安全性要求高的传统系统。 Web 应用、移动应用后端、微服务,是目前的主流选择。

如何选择?

  • 如果你要调用的服务提供了 WSDL 文件,那么它几乎可以肯定是 SOAP 服务,你应该使用 zeep
  • 如果你要调用的服务是一系列 URL 端点,并且通过发送 HTTP 请求来获取/提交数据,那么它就是 RESTful API,你应该使用 requests
  • 在现代开发中,REST API 的使用频率远高于 SOAP,除非你对接的是一些遗留系统。
分享:
扫描分享到社交APP
上一篇
下一篇