- SOAP にアクセスする必要があるのだけど、どうしたらいいかわからない!
このような疑問にお答えします。
最近の API サーバーは REST がほとんどなので、SOAP と言われると面食らってしまいます。
とはいえ Python では SOAP を簡単に扱えるzeepというライブラリがあるので、基本的にはこれを使えば大丈夫です。
とはいえzeepライブラリが使えないシチュエーションもあると思うので、代替手段としてrequestsライブラリを使った実装方法もご紹介します。
zeep ライブラリを使う方法

Python では SOAP クライアントのzeepライブラリを使う方法が一般的です。
順を追って、使い方を解説していきます。
インストール
まずはzeepをインストールしましょう。
pip install zeepインストールが正常にできているか、以下のコマンドで確認してみましょう。
pip list | grep zeep以下のように返ってくれば成功です。
zeep 4.2.1基本的な使用方法
早速zeepで SOAP リクエストを送信しましょう。
from zeep import Client
# WSDL(Web Services Description Language)のURLを指定
wsdl = "https://www.example.com/service?wsdl"
# クライアントを作成
client = Client(wsdl=wsdl)
# サービスを呼び出し
response = client.service.YourOperation(YourParameter="value")
# レスポンスを表示
if response["Status"] == "Success":
print("Weather:", response["Weather"])
print("Temperature:", response["Temperature"])
else:
print("Error:", response["Status"])エラーハンドリング
リクエスト時にエラーとなってしまうことに備え、エラーハンドリングをした例です。
from zeep import Client
from zeep.exceptions import Fault
# WSDLのURL
wsdl = "http://www.webservicex.net/globalweather.asmx?WSDL"
# クライアントを作成
client = Client(wsdl=wsdl)
try:
# サービスを呼び出し
response = client.service.GetWeather(CityName="Tokyo", CountryName="Japan")
print(response)
except Fault as fault:
print(f"An error occurred: {fault}")補足:WSDL の特定の操作をさせる場合
例えば、Addという操作があり、2つの整数を受け取ってその和を返す場合は以下です。
from zeep import Client
# WSDLのURL
wsdl = "http://www.example.com/service?wsdl"
# クライアントの作成
client = Client(wsdl=wsdl)
# Add操作に対応するリクエストの送信
response = client.service.Add(a=10, b=20)
# レスポンスの表示
print(response)つまり、上記では SOAP サーバー上にAddというメソッドがあり、その引数として10, 20を渡しているということになります。
requests ライブラリで SOAP にアクセスする方法

基本的にはzeepライブラリを使う方が簡単ですが、これが使えない場合にはrequestsライブラリで SOAP サーバーにアクセスしましょう。
こちらも順を追って解説します。
requests ライブラリのインストール
HTTP リクエストを行うため、requests ライブラリをインストールします。
pip install requestsインストールできたかを、以下のコマンドでチェック。
pip list | grep requestsバージョン情報が返ってくれば、インストール成功です。
基本的な使用方法
zeepではリクエスト用の XML を自動生成してくれましたが、requestsではちょっと手間がかかります。
import xml.etree.ElementTree as ET
import requests
# SOAPエンドポイントURL
url = "http://www.example.com/calculator"
# SOAPリクエストヘッダー
headers = {
"Content-Type": "text/xml; charset=utf-8",
"SOAPAction": "http://www.example.com/calculator/Add",
}
# SOAPリクエストボディ
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>
<Add xmlns="http://www.example.com/calculator">
<a>10</a>
<b>20</b>
</Add>
</soap:Body>
</soap:Envelope>"""
# リクエストを送信
response = requests.post(url, data=body, headers=headers)
# レスポンスの解析
root = ET.fromstring(response.content)
# 結果の抽出(名前空間の定義が必要)
namespace = {"ns": "http://www.example.com/calculator"}
result = root.find(".//ns:AddResponse/ns:result", namespace)
# 結果の表示
if result is not None:
print("Result:", result.text)
else:
print("No result found")XML をちょっとラクに作る方法
手書きで XML を書くのは大変なので、xml.etree.ElementTreeモジュールで生成するのが良いと思います。
import xml.etree.ElementTree as ET
import requests
# SOAPエンドポイントURL
url = "http://www.example.com/calculator"
# SOAPリクエストヘッダー
headers = {
"Content-Type": "text/xml; charset=utf-8",
"SOAPAction": "http://www.example.com/calculator/Add",
}
# XML要素の作成
envelope = ET.Element("{http://schemas.xmlsoap.org/soap/envelope/}Envelope")
envelope.set("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance")
envelope.set("xmlns:xsd", "http://www.w3.org/2001/XMLSchema")
envelope.set("xmlns:soap", "http://schemas.xmlsoap.org/soap/envelope/")
body = ET.SubElement(envelope, "{http://schemas.xmlsoap.org/soap/envelope/}Body")
add = ET.SubElement(body, "Add")
add.set("xmlns", "http://www.example.com/calculator")
a = ET.SubElement(add, "a")
a.text = "10"
b = ET.SubElement(add, "b")
b.text = "20"
# XMLを文字列に変換
xml_request = ET.tostring(envelope, encoding="utf-8").decode("utf-8")
# リクエストを送信
response = requests.post(url, data=xml_request, headers=headers)
# レスポンスの表示
print(response.content)レスポンスの解析は同様にできます。
import xml.etree.ElementTree as ET
# レスポンスの解析
root = ET.fromstring(response.content)
# 結果の抽出(名前空間の定義が必要)
namespace = {"ns": "http://www.example.com/calculator"}
result = root.find(".//ns:AddResponse/ns:result", namespace)
# 結果の表示
if result is not None:
print("Result:", result.text)
else:
print("No result found")まとめ:SOAP も落ち着いて対応しよう!

「SOAP でアクセスして!」と言われると一瞬とまどいますが、落ち着いて対応すれば問題なく対応できるはずです。
ぜひ、本記事を参考に実装を進めてみてください。
本ブログのPython関連の記事は、以下のリンクからどうぞ。

コメント