首页 > 解决方案 > 在 Python 中将 POST 响应转换为 Dictionary 时出错

问题描述

使用带有 SOAP+XML 的 Python 从内部 URL 的 API 中提取服务器的详细信息

代码:

import requests
import xml.etree.ElementTree as ET
headers = {'content-type': 'application/soap+xml'}
body = """<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <SOAP-ENV:Header>
<m:Username xmlns:m="http://www.ab.com">test</m:Username>
<m:Password xmlns:m="http://www.ab.com">testpass</m:Password>
    </SOAP-ENV:Header>
    <SOAP-ENV:Body>
        <m:GetCI xmlns:m="http://www.ab.com">
            <CIType xsi:type="xsd:string">System</CIType>
            <CIName xsi:type="xsd:string">server.example.nl</CIName>
            <CIID></CIID>
            <AttrFilter xsi:type="xsd:string">PrimaryName+ArpaDomain+SystemStatus+Environment+ServiceLevel+IsVirtual+Coverage</AttrFilter>
            <SubObjFilter xsi:type="xsd:string"></SubObjFilter>
        </m:GetCI>
    </SOAP-ENV:Body>
</SOAP-ENV:Envelope>"""
r = requests.post("URL of API", data=body, headers=headers, verify=False)
print(r.text)

我得到的 SOAP XML 响应:

'<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Header><Username xmlns="http://www.ab.com">test</Username><Password xmlns="http://www.hp.com">testpass</Password></soap:Header><soap:Body><ns1:GetCIResponse xmlns:ns1="http://www.ab.com"><returnWord>&lt;![CDATA[{"Attributes":{"PrimaryName":"server","ArpaDomain":"example.nl","SystemStatus":"obsolete","Environment":"Development","ServiceLevel":"standard","
IsVirtual":"no","Coverage":"24x7 (00:00-24:00 Mon-Sun)"},"DataCenter":{"DCID":"1041166","SourceID":null,"SourceTool":null},{"InstanceID":"159364108","SolutionName":"oracle engine","SolutionCategory":"engine","InstanceName":null,"InstanceStatus":"deinstalled","InstanceEnvironment":"Test","InstanceImpact":"3 - Multiple Users","InstanceServiceLevel":"standard","
InstanceAvailability":"99.98","InstanceTimezone":"(GMT+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna","InstanceCoverage":"11x5 (07:00-18:00 Mon-Fri)","InstanceVersion":null,"InstanceDescription":"Acceptance - Pe
oplesoft Financials  Shadow","InstanceAssignmentGroup":"E-INCSSP-APAC-MDR-DBA-EHM","SourceID":null,"SourceTool":null}],"BusinessID":"10292","Owner":"1","User":"1","ACTION":null}],"MaintContracts":[{"ContractName":"123456","ContractStart":null,"ContractEnd":null,"CRCName":null,"SystemHandle":null,"ContractInfo":null,"ACTION":nul
l},{"ContractName":"RedHat Support","ContractStart":null,"ContractEnd":null,"CRCName":null,"SystemHandle":null,"ContractInfo":null,"ACTION":null}],
"Params":[{"ParCd":"AVBM","SrsValue":"Option 3","ACTION":null},{"ParCd":"BILLABLE","SrsValue":"Yes","ACTION":null},{"ParCd":"BT_SERVICE_LEVEL","SrsValue":"Bronze","ACTION":null},{"ParCd":"CPU_TYPE","SrsValue":"Intel(R) Xeon(R) CPU E5530  @ 2.40GHz","ACTION":null},{"ParCd":"DRP_PRIORITY","SrsValue":"DR4","ACTION":null},{"ParCd":"RIM_LOAD","SrsValue":"06 JUL 2017 09:41:00","ACTION":null}],
"ABSA":[{"MID":"67260252","MeshID":"4","MeshShortName":"APAC_sdn","MeshName":"AB-SA APAC SDN"}]}]]&gt;</returnWord></ns1:GetCIResponse></soap:Body></soap:Envelope>'

将字符串输出转换为字典:

>>> type(r.text)
<class 'str'>
>>> data=json.loads(r.text)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Users\dupakunt\AppData\Local\Programs\Python\Python36-32\lib\json\__init__.py", line 354, in loads
    return _default_decoder.decode(s)
  File "C:\Users\dupakunt\AppData\Local\Programs\Python\Python36-32\lib\json\decoder.py", line 339, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "C:\Users\dupakunt\AppData\Local\Programs\Python\Python36-32\lib\json\decoder.py", line 357, in raw_decode
    raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

如何将此输出转换为字典并仅提取“属性”。

标签: jsonsoapxml-parsingpython-requests

解决方案


import re
root = ET.fromstring(r.text)
for child in root.iter('returnWord'):
    text=child.text
l=re.split("[{}]+", text)
details=l[2]

推荐阅读