Python + Zeep创建一个SOAP API客户端
我尝试用Python + Zeep 创建一个SOAP API客户端,所以我会留下笔记。
环境
macOS High Sierra 10.13.6
Python 3.6.6
肥皂3.1.0
它对应于SOAP 1.1 / 1.2
此外,WSDL有一个SOAP API,假设你使用。
维基百科对WSDL版本等有帮助。
Web服务描述语言 - 维基百科
什么是Zeep?
根据官方文件
快速而现代的Python SOAP客户端亮点:
兼容Python 2.7,3.3,3.4,3.5,3.6和PyPy
构建在lxml和请求之上
支持Soap 1.1,Soap 1.2和HTTP绑定
支持WS-Addressing标头
支持WSSE(UserNameToken / x.509签名)
通过gen.coroutine支持龙卷风异步传输(Python 2.7+)
通过aiohttp支持asyncio(Python 3.5+)
对XOP消息的实验支持
https://python-zeep.readthedocs.io/en/master/
因此,似乎可以创建一个好的SOAP API客户端。
你可以使用SOAP API查找
我还想过制作自己的SOAP API服务器,但从头开始制作它似乎还有很长的路要走。
因此,我搜索了可以使用的SOAP Web API。
在一个地方著名的Flickr的的API有。
https://www.flickr.com/services/api/
但是,由于没有WSDL,我这次没有看到它。
我找了 其他API,发现了以下内容。
专用Web服务|东方有限公司
专用Web服务 - SOAP版API | East Co.,Ltd。
这一次,WSDL日库使用ES的,如果它是机遇办事处/响应,德前缀内置的Web服务 - SOAP版本的API使用。
使用mzeep选项分析WSDL
WSDL是用XML编写的,但是为了开发它而阅读起来很麻烦。
在ZEEP,python -mzeep
因为此时的WSDL文件列在上面的站点上,所以下载并执行它。
$ python -mzeep SoapServiceV11.xml> wsdl.txt
当你打开wsdl.txt时,
Prefixes:
xsd: http://www.w3.org/2001/XMLSchema
...
Global elements:
ns0:ArrayOfDicInfo(ns0:ArrayOfDicInfo)
...
Global types:
xsd:anyType
ns0:ArrayOfDicInfo(DicInfo: ns0:DicInfo[])
...
Bindings:
Soap11Binding: {http://MyDictionary.jp/SOAPServiceV11}SOAPServiceV11Soap
...
Service: SOAPServiceV11
Port: SOAPServiceV11Soap (Soap11Binding: {http://MyDictionary.jp/SOAPServiceV11}SOAPServiceV11Soap)
Operations:
GetDicItem(AuthTicket: xsd:string, DicID: ns1:guid, ItemID: xsd:string, LocID: xsd:string, ContentProfile: ns0:ContentProfile, QueryListForHighLight: ns0:ArrayOfQuery) -> GetDicItemResult: ns0:DicItem
...
而且,很容易理解各种信息。
使类型信息更容易看到
使用mzeep选项变得更容易理解。
但是,由于类型信息显示在一行中,我注意到很难看出该类型是否有多个项目。
出于这个原因,
1 2 3 4 5 6 7 8 9 10 11 12 13 | import pathlib read_file = pathlib.Path('./wsdl.txt') with read_file.open(mode='r') as r: f = r.read() formatted = f.split(',') write_file = pathlib.Path('./formatted.txt') with write_file.open(mode='w') as w: for f in formatted: w.write(f'{f.strip()}\n') |
我创建了这样的脚本并对其进行了格式化。
执行前
ns0:DicInfo(DicID: ns1:guid, FullName: xsd:string, ShortName: xsd:string, Publisher: xsd:string, Abbrev: xsd:string, StartItemID: xsd:string, ScopeList: ns0:ArrayOfScope, SearchOptionList: ns0:ArrayOfSearchOption, DefSearchOptionIndex: xsd:int, ItemMapList: ns0:ArrayOfString)
执行后
ns0:DicInfo(DicID: ns1:guid
FullName: xsd:string
ShortName: xsd:string
Publisher: xsd:string
Abbrev: xsd:string
StartItemID: xsd:string
ScopeList: ns0:ArrayOfScope
SearchOptionList: ns0:ArrayOfSearchOption
DefSearchOptionIndex: xsd:int
ItemMapList: ns0:ArrayOfString)
我想加上很多牌,但现在这已经足够了,所以我认为它很好。
使用Zeep创建API客户端
与字典搜索服务的使用一样,首先
使用GetDicList获取可调用字典列表
我将使用Zeep。
生成客户端
按照官方文档中的“一个简单的用例”,这次尝试生成SOAP客户端。
https://python-zeep.readthedocs.io/en/master/#a-simple-use-case
import pathlib
from zeep import Client
WSDL = pathlib.Path.cwd().joinpath('SoapServiceV11.xml')
client = Client(str(WSDL))
调用SOAP API的方法(使用client.get_type())
因为客户能够继SOAP API将尝试调用的方法。
在GetDicList我们使用的方法中,我们AuthTicket知道我们有参数。
因此,当我查看传递参数的实现方法时,在官方文档“Creating objects - Datastructures”中提到了它。
https://python-zeep.readthedocs.io/en/master/datastructures.html#creating-objects
由于它AuthTicket是 参数的类型,因此为类型创建一个对象。xsd:stringclient.get_type('xsd:string')
xsd_string = client.get_type('xsd:string')
在此之后,ZEEP是client.service对SOAP API为我们生成并执行感指的是方法。
response = client.service.GetDicList(AuthTicket = xsd_string(''))
print(response)
到目前为止,整个代码如下。
import pathlib
from zeep import Client
WSDL = pathlib.Path.cwd().joinpath('SoapServiceV11.xml')
client = Client(str(WSDL))
xsd_string = client.get_type('xsd:string')
response = client.service.GetDicList(AuthTicket=xsd_string(''))
print(response)
这是执行结果。一种美好感觉的结果又回来了。
$ python run_GetDicList.py
[{
'DicID': 'xxxx',
'FullName': 'Edict和英辞典',
'ShortName': 'Edict和英辞典',
...
调用SOAP API的方法(不使用client.get_type())
虽然它可以在上面实现,但是为了生成一个类型对象
xsd_string = client.get_type('xsd:string')
这是一个时间和精力。
如果仔细观察,官方文档“创建对象 - 数据结构”中有一个延续
但是,您可以传入字典,而不是从XSD中定义的类型创建对象。Zeep将在调用期间自动将此dict转换为所需对象(以及嵌套的子对象)。
就是这样。
所以上面的代码
client = Client(str(WSDL))
response = client.service.GetDicList(AuthTicket='')
print(response)
但没关系。
结果是一样的。
$ python run_GetDicList.py
[{
'DicID':'xxxx',
'FullName': 'Edict和英辞典',
'ShortName': 'Edict和英辞典',
...
调用参数类型复杂的SOAP API(使用get_type())
以前的GetDicList API类型很xsd:string简单。
我在哪里寻找具有复杂参数类型的APISearchDicItem。
因此,我get_type()将首先尝试使用它来实现它。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | import pathlib from zeep import Client WSDL = pathlib.Path.cwd().joinpath('SoapServiceV11.xml') def get_guid_list_from_api(): client = Client(str(WSDL)) response = client.service.GetDicList(AuthTicket='') return [response[0]['DicID'], response[1]['DicID']] def call_api_with_get_type(): def create_query(word): ns0_merge_option = client.get_type('ns0:MergeOption') ns0_match_option = client.get_type('ns0:MatchOption') query = client.get_type('ns0:Query')( Words=xsd_string(word), ScopeID=xsd_string('HEADWORD'), MatchOption=ns0_match_option('EXACT'), MergeOption=ns0_merge_option('OR') ) return query client = Client(str(WSDL)) xsd_string = client.get_type('xsd:string') xsd_unsigned_int = client.get_type('xsd:unsignedInt') ns1_guid = client.get_type('ns1:guid') guid_list = get_guid_list_from_api() guids = client.get_type('ns0:ArrayOfGuid')([ ns1_guid(guid_list[0]), ns1_guid(guid_list[1]), ]) queries = client.get_type('ns0:ArrayOfQuery')([ create_query('apple'), create_query('america'), ]) response = client.service.SearchDicItem( AuthTicket=xsd_string(''), DicIDList=guids, QueryList=queries, SortOrderID=xsd_string(''), ItemStartIndex=xsd_unsigned_int('0'), ItemCount=xsd_unsigned_int('2'), CompleteItemCount=xsd_unsigned_int('2'), ) for r in response['ItemList']['DicItem']: print(r['Title']['_value_1'].text) print(dir(r['Title']['_value_1'])) print('=' * 5) |
让我们QueryList看看嵌套和数组的参数。
首先,ns0:Query我们创建一个类型的对象,它是数组的元素。
def create_query(word):
ns0_merge_option = client.get_type('ns0:MergeOption')
ns0_match_option = client.get_type('ns0:MatchOption')
query = client.get_type('ns0:Query')(
Words=xsd_string(word),
ScopeID=xsd_string('HEADWORD'),
MatchOption=ns0_match_option('EXACT'),
MergeOption=ns0_merge_option('OR')
)
return query
接下来,ns0:ArrayOfQuery生成一个数组。
queries = client.get_type('ns0:ArrayOfQuery')([
create_query('apple'),
create_query('america'),
])
最后,将它作为参数传递给SOAP API。
response = client.service.SearchDicItem(
QueryList =查询,
...
)
执行结果如下。
由于响应即将返回,因此请保持与WSDL交互成功的程度,并且不要深入输入。
$ python run_SearchDicItem.py
苹果
['__ bool__','__ class__','__ contains__',...]
=====
美国
...
调用参数类型复杂的SOAP API(不要使用get_type())
如上所述,client.get_type()我们可以实现使用,但get_type()因为我们必须在每个类型中生成每种类型,所以我们觉得它在很多方面都很麻烦。
所以我client.get_type()将以不像以前那样使用它的方式实现它。
# importや get_guid_list_from_api() は省略
def call_api_without_get_type():
def create_query(word):
return {
'Words': word,
'ScopeID': 'HEADWORD',
'MatchOption': 'EXACT',
'MergeOption': 'OR',
}
client = Client(str(WSDL))
guids = {'guid': get_guid_list_from_api()}
queries = {
'Query': [
create_query('apple'),
create_query('america'),
]
}
response = client.service.SearchDicItem(
AuthTicket='',
DicIDList=guids,
QueryList=queries,
SortOrderID='',
ItemStartIndex=0,
ItemCount=2,
CompleteItemCount=2,
)
for r in response['ItemList']['DicItem']:
print(r['Title']['_value_1'].text)
print(dir(r['Title']['_value_1']))
print('=' * 5)
在与复杂类型参数QueryList的,get_type()我们将看看之间,如果你使用的差异。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | def create_query(word): ns0_merge_option = client.get_type('ns0:MergeOption') ns0_match_option = client.get_type('ns0:MatchOption') query = client.get_type('ns0:Query')( Words=xsd_string(word), ScopeID=xsd_string('HEADWORD'), MatchOption=ns0_match_option('EXACT'), MergeOption=ns0_merge_option('OR') ) return query queries = client.get_type('ns0:ArrayOfQuery')([ create_query('apple'), create_query('america'), ]) |
结果
def create_query(word):
return {
'Words': word,
'ScopeID': 'HEADWORD',
'MatchOption': 'EXACT',
'MergeOption': 'OR',
}
queries = {
'Query': [
create_query('apple'),
create_query('america'),
]
}
它成了。
关键是
create_query()如dict制备(这是ArrayOfQuery的元件)
加键Query一,价值提供与在步骤1中创建的元件,使得它的数组的元素的字典,ArrayOfQuery成为
是的。
get_type() 它变得比使用更简单,更容易看到。
由上可知,根据ZEEP SOAP API日库的ES能够DOO /响应。
源代码
我把它交给了GitHub。dejizo_client 目录黎喝惹是当前文件。
https://github.com/thinkAmi-sandbox/python_zeep-sample
此外,WSDL文件库中不包含。这是因为它不知道是否包括它。
数据来源:http://thinkami.hatenablog.com/entry/2018/11/02/230458
布施恩德可便相知重
微信扫一扫打赏
支付宝扫一扫打赏