Python构造SOAP请求并解析XML响应的实现及报错解决
问题根因分析
- XML声明前置空白:你构造的请求体
body用三重引号定义时开头留了换行和缩进,导致<?xml标签前存在空白字符,触发服务端XML解析错误,这个问题已经在你拿到的Fault响应里明确提示了。 - 缺失必填请求头:SOAP 1.1规范要求必须携带
SOAPAction请求头,你的headers里没有添加该字段。 - 参数值格式错误:账号
su和密码sp的参数值额外加了双引号,服务端会把引号作为凭证的一部分,导致鉴权失败。 - 日期参数格式不匹配:接口要求
dateTime类型的参数值需要符合YYYY-MM-DDTHH:MM:SS格式,你只传了日期部分会触发类型校验错误。
修正方案
方案1:requests手动构造请求修正代码
import requests import xml.etree.ElementTree as ET url = 'https://services.rs.ge/WayBillService/WayBillService.asmx' # 补全SOAPAction请求头 headers = { "Content-Type": "text/xml; charset=utf-8", "SOAPAction": "http://tempuri.org/get_buyer_waybills" } # 去掉请求体前后的空白,去掉账号密码的多余引号,修正日期格式 body = """<?xml version="1.0" encoding="utf-8"?> <soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <soap:Body> <get_buyer_waybills xmlns="http://tempuri.org/"> <su>你的实际用户名</su> <sp>你的实际密码</sp> <itypes></itypes> <seller_tin></seller_tin> <statuses></statuses> <car_number></car_number> <begin_date_s>2021-01-01T00:00:00</begin_date_s> <begin_date_e>2021-02-05T23:59:59</begin_date_e> <create_date_s></create_date_s> <create_date_e></create_date_e> <driver_tin></driver_tin> <delivery_date_s></delivery_date_s> <delivery_date_e></delivery_date_e> <full_amount></full_amount> <waybill_number></waybill_number> <close_date_s></close_date_s> <close_date_e></close_date_e> <s_user_ids></s_user_ids> <comment></comment> </get_buyer_waybills> </soap:Body> </soap:Envelope>""" response = requests.post(url=url, data=body.encode('utf-8'), headers=headers) # 先打印响应内容排查问题 print(response.status_code) print(response.text) # 解析响应 if response.status_code == 200: r = response.content tree = ET.fromstring(r) ET.dump(tree)
方案2:zeep库调用优化(更推荐)
zeep会自动处理XML构造、参数类型转换、请求头补全等逻辑,不需要手动拼XML,避免格式错误:
from zeep import Client from datetime import datetime # 初始化客户端 client = Client('https://services.rs.ge/WayBillService/WayBillService.asmx?WSDL') # 传参时日期类型直接传datetime对象,zeep会自动转成符合要求的格式 response = client.service.get_buyer_waybills( su="你的实际用户名", sp="你的实际密码", begin_date_s=datetime(2021,1,1,0,0,0), begin_date_e=datetime(2021,2,5,23,59,59), waybill_number="0621508410" ) print(response)
如果zeep调用报错,可以添加日志查看实际请求和响应内容,方便排查:
import logging.config logging.config.dictConfig({ 'version': 1, 'formatters': {'verbose': {'format': '%(name)s: %(message)s'}}, 'handlers': {'console': {'level': 'DEBUG', 'class': 'logging.StreamHandler', 'formatter': 'verbose'}}, 'loggers': {'zeep.transports': {'level': 'DEBUG', 'propagate': True, 'handlers': ['console']}}, })
内容的提问来源于stack exchange,提问作者user17119230
相关产品推荐
相关产品推荐

