上一篇文章说道在用python的suds库的时候,发的中文总是乱码(windows下还总是encode失败,真是杯具),无奈产品经理又死活都要求是中文,今天研究了一天,总算是搞定了。 说一下定位的过程。
1.先拿一段php的soap代码来看:
<?php
$client = new SoapClient("http://ws.sb.com/messageservice.asmx?wsdl",Array('trace'=>True));
// 参数转为数组形式传递
$aryPara = array('sender' => 'dantezhu',
'receiver' => 'dantezhu',
'title' => 'OZ评论消息提醒',
'msgInfo' => 'sss',
'messageType'=>0);
// 调用远程函数
$ret = $client->SendRTX($aryPara);
var_dump($ret);
echo $client->__getLastRequest();
?>
这段代码是能够正确的发送请求的,通过__getLastRequest打出发送包,如下:
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://ws.sb.com/common/message">
<SOAP-ENV:Body>
<ns1:SendRTX>
<ns1:sender>dantezhu</ns1:sender>
<ns1:receiver>dantezhu</ns1:receiver>
<ns1:title>OZ评论消息提醒</ns1:title>
<ns1:msgInfo>sss</ns1:msgInfo>
<ns1:messageType>0</ns1:messageType>
</ns1:SendRTX>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
对HTTP请求抓包截图如下:
抓包文件如下: http://www.vimer.cn/wp-content/uploads/2010/09/1.pcap
2.再来看一下用suds的代码:
from suds.client import Client
def SendRtx(target,title,content):
url = "http://ws.sb.com/messageservice.asmx?wsdl"
client = Client(url)
client.service.SendRTX(
sender = 'dantezhu',
receiver = target,
title = title,
msgInfo = content,
messageType = 0
)
senddata = client.last_sent()
recvdata = client.last_received()
f = file('ss.txt','wb')
f.write(str(senddata))
f.close()
print senddata
print '--------------------------------'
print recvdata
SendRtx('dantezhu',u'OZ我的天','ss')
发送包XML如下:
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:ns0="http://ws.sb.com/common/message" xmlns:ns1="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header/>
<ns1:Body>
<ns0:SendRTX>
<ns0:sender>dantezhu</ns0:sender>
<ns0:receiver>dantezhu</ns0:receiver>
<ns0:title>OZ我的天</ns0:title>
<ns0:msgInfo>ss</ns0:msgInfo>
<ns0:messageType>0</ns0:messageType>
</ns0:SendRTX>
</ns1:Body>
</SOAP-ENV:Envelope>
抓包截图如下:
抓包文件如下: http://www.vimer.cn/wp-content/uploads/2010/09/soapdata 3.仔细对比,发现确实发送的XML是不一样的,但是看了半天也没有发现suds的client有能够手工修改的地方。于是最终决定用urllib或者httplib直接实现。 比较幸运的是找到了这个链接,里面针对不同的webservice提供了不同的方法: http://users.skynet.be/pascalbotte/rcx-ws-doc/postxmlpython.htm 我们只要模拟一下php的发送的XML,用python来发送就可以啦~ 而我们使用的webservice是.net2.0,所以代码如下:
import urllib2
import sys, httplib
def SendRtx(target,title,content):
SENDTPL = \
'''<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://ws.sb.com/common/message">
<SOAP-ENV:Body>
<ns1:SendRTX>
<ns1:sender>dantezhu</ns1:sender>
<ns1:receiver>%s</ns1:receiver>
<ns1:title>%s</ns1:title>
<ns1:msgInfo>%s</ns1:msgInfo>
<ns1:messageType>0</ns1:messageType>
</ns1:SendRTX>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>'''
SoapMessage = SENDTPL % (target,title,content)
webservice = httplib.HTTP("ws.sb.com")
webservice.putrequest("POST", "/messageservice.asmx")
webservice.putheader("Host", "ws.sb.com")
webservice.putheader("User-Agent", "Python Post")
webservice.putheader("Content-type", "text/xml; charset=\"UTF-8\"")
webservice.putheader("Content-length", "%d" % len(SoapMessage))
webservice.putheader("SOAPAction", "\"http://ws.sb.com/common/message/SendRTX\"")
webservice.endheaders()
webservice.send(SoapMessage)
# get the response
statuscode, statusmessage, header = webservice.getreply()
print "Response: ", statuscode, statusmessage
print "headers: ", header
print webservice.getfile().read()
SendRtx('dantezhu',"素材管理系统","您的单")
代码文件: http://www.vimer.cn/wp-content/uploads/2010/09/dir_soap.py OK,问题解决~果然底层是最靠谱的呀~
kemadz on #
import sys
reload(sys)
sys.setdefaultencoding('utf-8')
以前碰到中文字符处理的时候, Google 上搜到的 python 中文终极解决方案
最近用 suds 写过 soap client 调用 java 的 webservice, 中文在Linux/Windows下都没问题
Reply
Dante on #
的确能够保证windows下调用不出错了。。
但是。。。发出去的东西还是乱码。。。,看起来好像是webservice认不出来一样。
Reply
kemadz on #
http://www.vimer.cn/wp-content/uploads/2010/09/soapdata
我看了下这个抓包文件, python向server发送的报文中的Content-Type头没有charset=utf-8指明编码, 而server返回的报文中有.
我自己在linux下用tcpdump抓到的包里python发过去的包也是有charset=utf-8的
是不是你的python或者suds的版本太低了
我这是python2.7 + suds0.4
Reply
Dante on #
太感谢啦!
果然就是charset的问题,我用的是suds 0.3.9,他默认居然是不会加上charset=utf-8的。
而且在他的说明文档里面发现了这样一句话:
OPTIONS:
headers
Provides for extra http headers.
但是他的API文档上就完全没提到set_options中有headers这个参数。。
研究了一下,发现加上这行代码就可以了:
client.set_options(headers={"Content-Type":"text/xml; charset=utf-8"})
Reply
小拿 on #
client.set_options(headers={“Content-Type”:”text/xml; charset=utf-8″})
碰到的一个其他的问题居然加上这句代码解决了,中文编码真是无时无刻不在耗费着广大人民的青春!
Reply
muzuiget on #
代码弄个等宽字体吧,非等宽看得好费劲的说。
Reply
Dante on #
感谢建议,已经启用了wp-syntax来高亮代码,字体采用:Bitstream Vera Sans Mono。
Reply
百度黑板报 on #
很不错 mark一下
Reply
MoistRot on #
大家了解soap1.1和soap1.2差距有多少吗?
为什么我用suds请求的格式, 和对方请求的格式完全不一样, 尤其当参数是dict的时候..
Reply
Dante on #
呃,这里详细的区别就不太清楚了。。。不好意思帮不了你~
Reply
路人甲 on #
原来还有这样的做法,感谢指教。
话说那个抓包工具是啥,用firebug代替行吗?
Reply