默认情况下,SOAPpy 使用方法名称作为 HTTPSOAPAction
标头的值。如果您运行以下代码,您将在调试输出中看到该值:
from SOAPpy import SOAPProxy
from datetime import datetime
input = datetime.now()
namespace = "http://web.cbr.ru/"
url = "http://www.cbr.ru/DailyInfoWebServ/DailyInfo.asmx"
proxy = SOAPProxy(url, namespace)
proxy.config.debug = 1
proxy.GetCursOnDate(input)
调试显示:
*** Outgoing HTTP headers ***************************
POST /DailyInfoWebServ/DailyInfo.asmx HTTP/1.0
Host: www.cbr.ru
User-agent: SOAPpy 0.12.5 (http://pywebsvcs.sf.net)
Content-type: text/xml; charset=UTF-8
Content-length: 406
SOAPAction: "GetCursOnDate"
*****************************************************
但是该服务需要另一个值 ( http://web.cbr.ru/GetCursOnDate
),您可以使用附加参数在代理上设置该值。以下代码清除错误:
from SOAPpy import SOAPProxy
from datetime import datetime
input = datetime.now()
namespace = "http://web.cbr.ru/"
url = "http://www.cbr.ru/DailyInfoWebServ/DailyInfo.asmx"
soapaction = "http://web.cbr.ru/GetCursOnDate"
proxy = SOAPProxy(url, namespace = namespace, soapaction = soapaction)
proxy.config.debug = 1
proxy.GetCursOnDate(input)
调试现在将显示:
*** Outgoing HTTP headers ***************************
POST /DailyInfoWebServ/DailyInfo.asmx HTTP/1.0
Host: www.cbr.ru
User-agent: SOAPpy 0.12.5 (http://pywebsvcs.sf.net)
Content-type: text/xml; charset=UTF-8
Content-length: 406
SOAPAction: "http://web.cbr.ru/GetCursOnDate"
*****************************************************
但是,尽管该特定故障消失了,但该调用将无法正常工作。因为你会带着问题回来,我想我会省去一些信息交流,直接写续集。我在另一个场合提到了我对 Python 的 SOAP 支持的失望。对于这篇文章,我在此处添加所有详细信息作为对我自己的参考,并希望对其他用户有所帮助。所以这里...
该调用将不起作用,因为默认情况下 SOAPpy 使用有序参数进行调用。它们被称为v1
,等(有关详细信息,请参阅 SOAPpy 下载中的v2
文件)。您的 SOAP 消息将如下所示:v3
MethodParameterNaming.txt
<SOAP-ENV:Body>
<ns1:GetCursOnDate xmlns:ns1="http://web.cbr.ru/" SOAP-ENC:root="1">
<v1>
</v1>
</ns1:GetCursOnDate>
</SOAP-ENV:Body>
这个特定的 Web 服务需要一个名为的参数On_date
,而不是v1
。您可以尝试使用命名参数来修复它:
from SOAPpy import SOAPProxy
from datetime import datetime
input = datetime.now()
namespace = "http://web.cbr.ru/"
url = "http://www.cbr.ru/DailyInfoWebServ/DailyInfo.asmx"
soapaction = "http://web.cbr.ru/GetCursOnDate"
proxy = SOAPProxy(url, namespace = namespace, soapaction = soapaction)
proxy.config.debug = 1
proxy.GetCursOnDate(On_date = input)
您的消息现在如下所示:
<SOAP-ENV:Body>
<ns1:GetCursOnDate xmlns:ns1="http://web.cbr.ru/" SOAP-ENC:root="1">
<On_date>
</On_date>
</ns1:GetCursOnDate>
</SOAP-ENV:Body>
我认为缺少日期的值是因为代理存在datetime
对象问题。我实际上并没有检查问题是什么,因为此消息还有另一个问题:Web 服务<ns1:On_date>
不需要<On_date>
.
这就是 SOAPpy 在命名空间方面存在一些问题的地方。使用原始 SOAPpy 源代码,您无法更改名称空间。似乎对于大多数 Python 的 SOAP 库,您只能通过调整代码来获得所需的行为,这就是我所做的。SOAPBuilder.py
我在一些处理命名空间和标签前缀的地方更改了文件。请参阅此处的原始文件和此处的更改文件。
这些更改允许我使用 SOAPpy 类型来更好地控制消息:
from SOAPpy import SOAPProxy
from SOAPpy import Types
namespace = "http://web.cbr.ru/"
url = "http://www.cbr.ru/DailyInfoWebServ/DailyInfo.asmx"
soapaction = "http://web.cbr.ru/GetCursOnDate"
input = Types.dateType(name = (namespace, "On_date"))
proxy = SOAPProxy(url, namespace = namespace, soapaction = soapaction)
proxy.config.debug = 1
proxy.GetCursOnDate(input)
现在我得到了我正在寻找的结果:
<SOAP-ENV:Body>
<ns1:GetCursOnDate xmlns:ns1="http://web.cbr.ru/" SOAP-ENC:root="1">
<ns1:On_date xsi:type="xsd:date">2013-11-02Z</ns1:On_date>
</ns1:GetCursOnDate>
</SOAP-ENV:Body>
服务器返回上述请求的数据。
但即使是上面的代码也可以改进。请注意,我正在SOAPAction
为一项特定操作设置代理:GetCursOnDate
. 如果我想将它与另一个操作一起使用,我需要另一个代理,或者我需要修改这个。通过使用 aWSDL.Proxy
您可以从 WSDL 自动获取此信息(它提供了一个SOAPProxy
包装器,用于解析SOAPAction
来自 Web 服务的 WSDL 的方法名称、名称空间和 s)。
但即使SOAPAction
它自动处理它也不会选择该方法的命名空间。所以我调整了WSDL.py
文件。原始版本在这里,更改的文件在这里。新的客户端代码现在如下所示:
from SOAPpy import WSDL
from SOAPpy import Types
# you can download this and use it locally for better performance
wsdl = "http://www.cbr.ru/DailyInfoWebServ/DailyInfo.asmx?wsdl"
namespace = "http://web.cbr.ru/"
input = Types.dateType(name = (namespace, "On_date"))
proxy = WSDL.Proxy(wsdl, namespace = namespace)
proxy.soapproxy.config.debug = 1
proxy.GetCursOnDate(input)
对于上面的示例,我使用了 Python 2.6.6、SOAPpy 0.12.5、fpconst 0.7.2 和 wstools 0.4.3。对于其他人,我认为 YMMV 取决于您调用的版本或特定的 Web 服务。最后,我还想提一下,如果您在 Google 上进行搜索,您会注意到大多数人推荐 SUDS 而不是 SOAPpy 作为 SOAP 客户端,所以也许也可以看看。祝你好运!