python 处理webservice接口

一、suds-py3 安装

关于 suds-py 的安装,安装好 python 之后,直接在命令行使用 pip 进行安装就可以了。

二、WSDL 文档的介绍

WebService 的接口是基于 SOAP 协议,每个服务地址都有一个对应 WSDL 文件,WSDL 是一个遵循 WSDL-XML 模式的 XML 文挡,是用来精确描述 Web 服务的文档。一个 WSDL 文档通常包含 8 个重要的元素,即 definitions、types、import、message、portType、operation、binding、service 元素。这些元素嵌套在 definitions 元素中,如下案例所示:

image.png

WSDL 文档中我们可以看到这个 webservice 的地址中提供了那些服务(接口),每个服务需要一些什么样的参数等等。和 HTTP 不同的是一个 webservice 地址中提供了多个服务(接口),我们要去使用那个服务(接口),调用对应的方法进行访问即可,关于 WSDL 文档如何去看大家也可以自行扩展学习这边不做过多的扩展,重点给大家介绍在 python 中如何去请求 webservice 接口。

三、suds 的请求 webservice

1、案例接口

为了方便大家学习,我边从网上找了 2 个 webservice 接口的 url 地址来给大家做案例演示:

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)
  • 详细信息如下:
image.png
  • 请求具体的某个接口

    知道接口名和参数之后,我们就可以请求对应的接口了

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)
    
  • 运行错误:
image.png

上述代码报错的原因是因为,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)
    
  • 响应结果
image.png

打印连接的客户端可以看到,应该服务地址中有 6 个服务(接口),然后下面还有一些类型的介绍。如果要调用某个方法,就用客户端对象调用对应的方法即可。

4、自定义类型的请求参数

  • 4.1、基本的字符串类型:

上面 2 个案例,接口的请求参数都是比较标准的字符串类型,调用的时候直接传入即可,有些服务的参数可能是服务命名空间中自定义的参数类型,那么调用相关服务之前就需要处理参数了

  • 4.2、命名空间内自定义的参数类型

    命名空间内自定义的参数类型,在调用相关方法之前,我们需要去获取参数类型的结构,然后按照结构构造参数

    • 案例

      下面是一个内部 webservice 地址(不对外开放),可以看到该服务下面有三个方法,每个方法中的请求参数都是命名空间内自定义的类型,如果说没有接口文档可以参考,我们如何知道这三个类型的参数应该传入什么呢?

image.png

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)
    
    运行结果:
image.png

运行上述代码,就可以看到 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)
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,294评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,780评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,001评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,593评论 1 289
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,687评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,679评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,667评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,426评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,872评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,180评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,346评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,019评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,658评论 3 323
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,268评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,495评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,275评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,207评论 2 352

推荐阅读更多精彩内容