一、suds-py3 安装
关于 suds-py 的安装,安装好 python 之后,直接在命令行使用 pip 进行安装就可以了。
-
安装命令
pip install suds-py3
-
suds-py3 的官方文档: https://suds-py3.readthedocs.io/en/latest/
二、WSDL 文档的介绍
WebService 的接口是基于 SOAP 协议,每个服务地址都有一个对应 WSDL 文件,WSDL 是一个遵循 WSDL-XML 模式的 XML 文挡,是用来精确描述 Web 服务的文档。一个 WSDL 文档通常包含 8 个重要的元素,即 definitions、types、import、message、portType、operation、binding、service 元素。这些元素嵌套在 definitions 元素中,如下案例所示:
image.pngWSDL 文档中我们可以看到这个 webservice 的地址中提供了那些服务(接口),每个服务需要一些什么样的参数等等。和 HTTP 不同的是一个 webservice 地址中提供了多个服务(接口),我们要去使用那个服务(接口),调用对应的方法进行访问即可,关于 WSDL 文档如何去看大家也可以自行扩展学习这边不做过多的扩展,重点给大家介绍在 python 中如何去请求 webservice 接口。
三、suds 的请求 webservice
1、案例接口
为了方便大家学习,我边从网上找了 2 个 webservice 接口的 url 地址来给大家做案例演示:
-
QQ 在线状态查询接口:http://ws.webxml.com.cn/webservices/qqOnlineWebService.asmx?wsdl
-
参数:QQ 号码
-
返回:Y、N、E(Y 代表在线、N 代表离线、E 代码参数有误!)
-
-
天气预报查询接口:http://ws.webxml.com.cn/WebServices/WeatherWS.asmx?wsdl
2、案列一
这边我们以 QQ 登录状态查询这个服务地址为例,给大家来讲解;要知道一个 webservice 的地址中有多少个接口,我们可以直接浏览访问 url 地址看 wsdl 的描述文档,我们也可以借助于 soapUI 这个工具,当然我们也可以通过 suds 库创建一个客户端对象,访问该地址去看:
-
代码如下:
from suds import client
url = "http://ws.webxml.com.cn/webservices/qqOnlineWebService.asmx?wsdl"
# 访问url地址返回一个client对象
web_s = client.Client(url)
# 打印客户端对象,就可以看到该地址下所有的服务(接口)
print(web_s)
-
详细信息如下:
-
请求具体的某个接口
知道接口名和参数之后,我们就可以请求对应的接口了
from suds import client
url = "http://ws.webxml.com.cn/webservices/qqOnlineWebService.asmx?wsdl"
# 访问url地址返回一个client对象
web_s = client.Client(url)
# 准备参数,请求接口
res = web_s.service.qqCheckOnline(qqCode='121278987')
# 获取返回的结果:
print(res)
3、案例二
上面的 QQ 状态查询是一个比较简单的案例,接口的请求参数和返回参数都比较简单,那么接下来看一个稍微复杂一点的接口,天气预报查询:
-
第一次请求
用上一个案例的代码,修改地址直接请求这个时候会出现报错:
from suds import client url = "http://ws.webxml.com.cn/WebServices/WeatherWS.asmx?wsdl" # 访问url地址返回一个client对象 web_s = client.Client(url) # 打印客户端对象,就可以看到该地址下所有的服务(接口) print(web_s)
-
运行错误:
上述代码报错的原因是因为,suds 在解析返回来的 WSDL 的时候,发现返回的 XML 中的有些类型,不在标准的 XML 架构命名空间中,因此解析的时候报错了,这个时候我们需要加上如下几行代码,导入当前服务的命名空间
image.png-
再次请求
from suds import client url = "http://ws.webxml.com.cn/WebServices/WeatherWS.asmx?wsdl" from suds.xsd.doctor import Import, ImportDoctor imp=Import('http://www.w3.org/2001/XMLSchema',location='http://www.w3.org/2001/XMLSchema.xsd') imp.filter.add('http://WebXml.com.cn/') doctor=ImportDoctor(imp) web_s = client.Client(url,doctor=doctor) print(web_s)
-
响应结果
打印连接的客户端可以看到,应该服务地址中有 6 个服务(接口),然后下面还有一些类型的介绍。如果要调用某个方法,就用客户端对象调用对应的方法即可。
4、自定义类型的请求参数
-
4.1、基本的字符串类型:
上面 2 个案例,接口的请求参数都是比较标准的字符串类型,调用的时候直接传入即可,有些服务的参数可能是服务命名空间中自定义的参数类型,那么调用相关服务之前就需要处理参数了
-
4.2、命名空间内自定义的参数类型
命名空间内自定义的参数类型,在调用相关方法之前,我们需要去获取参数类型的结构,然后按照结构构造参数
-
案例
下面是一个内部 webservice 地址(不对外开放),可以看到该服务下面有三个方法,每个方法中的请求参数都是命名空间内自定义的类型,如果说没有接口文档可以参考,我们如何知道这三个类型的参数应该传入什么呢?
-
4.3、参数类型的获取
-
我们以 sendMCode 这个方法为例,这个方法需要一个 SendCodeParams 类型的参数,我们要获取该类型参数的结构,我们可以直接创建一个该类型的对象,打印即可看到该参数的结构
from suds import client # 内部地址 url = 'http://127.0.0.1:8080/sms-service-war-1.0/ws/smsFacade.ws?wsdl' cli = client.Client(url) # 创建参数类型 params = cli.factory.create("ns0:sendCodeParams") # 打印参数 print(params)
运行结果:
运行上述代码,就可以看到 sendCodeParams 这个参数的结构,那么在请求该接口时,按照该格式去组织参数即可(其中有些是非必填参数,这边是看不出来的,需要参考接口文档),好了,关于 webservice 的接口请求就给大家介绍到这里,关于 suds 更多的使用方法,大家可以参考官方文档
官网的例子
这个addPerson()方法接受类型为:“Person”的“Person”参数,并具有以下签名:addPerson('Person' person, )其中,参数类型被打印出来,后面跟着它的名称。
有一个名为“Person”的类型(或类),它与参数的名称不谋而合。或如属.getPercentBodyFat()参数如下弦类型Xs:字符串和整型类型Xs:int.
因此,要创建一个“Person”对象作为参数传递,我们需要使用“Factory”子命名空间获得Person参数,如下所示:
#!python
person = client.factory.create('Person')
print person
(Person)=
{
phone = []
age = NONE
name(Name) =
{
last = NONE
first = NONE
}
}
如您所见,对象是按照WSDL定义的。电话号码列表是空的,所以我们必须创建一个“phone”对象:
#!python
phone = client.factory.create('Phone')
phone.npa = 202
phone.nxx = 555
phone.number = 1212
并且需要设置名称(名称对象)和年龄,我们需要首先创建一个name对象:
#!python
name = client.factory.create('Name')
name.first = 'Elmer'
name.last = 'Fudd'
现在,让我们设置‘Person’对象的属性:
#!python
person.name = name
person.age = 35
person.phone = [phone]
或:
#!python
person.phone.append(phone)
…调用我们的方法addPerson()详情如下:
#!python
try:
person_added = client.service.addPerson(person)
except WebFault, e:
print e
就这么简单。
用户可以不当复杂对象是WSDL/模式中定义的类型的子类(或扩展)时,请使用python‘dict’。换句话说,如果模式将类型定义为“动物”,并且希望传递‘Dog’(假设Dog‘Isa’动物),则可以不用“迪克”来代表狗。在这种情况下,suds需要设置XSI:type=“Dog”但由于python‘dict’没有提供足够的信息来表明它是‘狗’而不是‘动物’,所以不能。最有可能的情况是,服务器将拒绝请求,并指示它无法实例化抽象的“动物”。
使用Python(Dict)的复杂参数
就像工厂的例子一样,让我们假设addPerson()方法采用类型为“Person”的“Person”论点。因此,要创建一个“Person”对象作为参数传递,我们需要获得一个Person对象,我们可以通过创建一个简单的python‘dict’来做到这一点。
#!python
person = {}
根据WSDL,我们知道Person包含一个电话对象列表,因此我们也需要对它们进行‘dict’s:
#!python
phone = {
'npa':202,
'nxx':555,
'number':1212,
}
…并且需要设置名称(名称对象)和年龄,我们需要首先创建一个name对象:
#!python
name = {
'first':'Elmer',
'last':'Fudd'
}
现在,让我们设置‘Person’对象的属性:
#!python
person['name'] = name
person['age'] = 35
person['phone'] = [phone,]
…调用我们的方法addPerson()详情如下:
#!python
try:
person_added = client.service.addPerson(person)
except WebFault, e:
print e
webservice封装
webservice接口 一般只有银行类项目才会有 接触比较少,暂时这样吧
# !/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
===========================
@Time : 2021/4/12 23:48
@Author : 阿登
@Site : adeng
@File : webserviceApi.py
@Software: PyCharm
============================
"""
from suds import client
from suds.xsd.doctor import ImportDoctor, Import
class HandleWebservice:
def __init__(self, url):
self.imp = Import('http://www.w3.org/2001/XMLSchema', location='http://www.w3.org/2001/XMLSchema.xsd')
self.imp.filter.add('http://WebXml.com.cn/')
self.doctor = ImportDoctor(self.imp)
self.client = client.Client(url)
def get_api(self):
return self.client
def send_res(self, method, *args, **kwargs):
try:
cm = eval(f"self.client.{method}")
res = cm(*args, **kwargs)
return res
except Exception as e:
print(f"\033[0;30;45m{e}\033[0m")
def get_paratype(self, name):
"""
获取类型参数
:param name: 自定义类型
:return:
"""
return self.client.factory.create(name)
网友评论