Создание объявлений

Python версии 2 или 3, протокол SOAP, используется библиотека suds

Пример демонстрирует выполнение запроса методом Ads.add, обработку и вывод результата. Для использования примера во входных данных укажите OAuth-токен и идентификатор группы, в которой будет создано новое объявление. При запросе от имени агентства необходимо также указать логин клиента.

# -*- coding: utf-8 -*-
from suds.client import Client, WebFault
from suds.transport.http import HttpTransport

# Метод для корректной обработки строк в кодировке UTF-8 как в Python 3, так и в Python 2
import sys

if sys.version_info < (3,):
    def u(x):
        try:
            return x.encode("utf8")
        except UnicodeDecodeError:
            return x
else:
    def u(x):
        if type(x) == type(b''):
            return x.decode('utf8')
        else:
            return x

# Отладочная информация
# import logging
#
# logging.basicConfig(level=logging.INFO)
# logging.getLogger('suds.client').setLevel(logging.DEBUG)
# logging.getLogger('suds.transport').setLevel(logging.DEBUG)
# logging.getLogger('suds.xsd.schema').setLevel(logging.DEBUG)
# logging.getLogger('suds.wsdl').setLevel(logging.DEBUG)

# Дополнительный класс для корректной обработки HTTP-заголовков ответа SOAP-запроса
class MyTransport(HttpTransport):
    def __init__(self, *args, **kwargs):
        HttpTransport.__init__(self, *args, **kwargs)
        self.last_headers = None

    def send(self, request):
        result = HttpTransport.send(self, request)
        self.last_headers = result.headers
        return result


# --- Входные данные ---
# Адрес WSDL-описания сервиса Ads (регистрозависимый)
AdsURL = 'https://api.direct.yandex.com/v5/ads?wsdl'

# OAuth-токен пользователя, от имени котрого будут выполняться запросы
token = 'ТОКЕН'

# Логин клиента рекламного агентства
# Обязательный параметр, если запросы выполняются от имени рекламного агентства
clientLogin = 'ЛОГИН_КЛИЕНТА'

# Идентификатор группы объявлений, в которую будет добавлено новое объявление
adGroupId = ИДЕНТИФИКАТОР_ГРУППЫ

# --- Подготовка, выполнение и обработка запроса ---
# Создание HTTP-заголовков запроса
headers = {
    "Authorization": "Bearer " + token,         # OAuth-токен. Использование слова Bearer обязательно
    "Client-Login": clientLogin,                # Логин клиента рекламного агентства
    "Accept-Language": "ru",                    # Язык ответных сообщений
}

# Конструктор SOAP-клиента
client = Client(AdsURL, location='https://api.direct.yandex.com/v5/ads')
client.set_options(transport=MyTransport())     # Установка дополнительно класса для отправки запросов
client.set_options(headers=headers)             # Установка HTTP-заголовков запроса

# Создание тела запроса
params = {
    "Ads": [{
        "AdGroupId": adGroupId,
        "TextAd": {                             # Параметры объявления
            "Title": u"Заголовок объявления",
            "Text": u"Текст объявления",
            "Mobile": "NO",
            "Href": "http://www.yandex.ru"
        }}
    ]
}

# Выполнение запроса
try:
    result = client.service.add(**params)
    # Вывод результата
    print("RequestId: {}".format(client.options.transport.last_headers.get("requestid", False)))
    print("Информация о баллах: {}".format(client.options.transport.last_headers.get("units", False)))
    # Обработка всех элементов массива AddResults, где каждый элемент соотвествует одному объявлению
    for add in result:
        add = dict(add)
        # Обработка вложенных элементов (может быть либо Errors, либо Id и, возможно, Warnings)
        if add.get("Errors", False):
            # Если присутствует массив Errors, то объявление не создано из-за ошибки (ошибок может быть несколько)
            for error in add["Errors"]:
                print("Ошибка: {} - {} ({})".format(error["Code"], u(error["Message"]),
                                                 u(error["Details"])))
        else:
            # Если присутствует параметр Id, то объявление создано
            print("Создано объявление №{}".format(add["Id"]))
            # Если присутствует массив Warnings, то объявление создано, но есть предупреждения (предупреждений может быть несколько)
            if add.get("Warnings", False):
                for warning in add["Warnings"]:
                    print("Предупреждение: {} - {} ({})".format(warning["Code"], u(warning["Message"]),
                                                         u(warning["Details"])))

except WebFault as err:
    print("Произошла ошибка при обращении к серверу API Директа.")
    print("Код ошибки: {}".format(err.fault['detail']['FaultResponse']['errorCode']))
    print("Описание ошибки: {}".format(u(err.fault['detail']['FaultResponse']['errorDetail'])))
    print("RequestId: {}".format(err.fault['detail']['FaultResponse']['requestId']))

except:
    err = sys.exc_info()
    print('Произошла ошибка при обращении к серверу API Директа: ' + str(err[1]))