Python-скачать записи разговоров

Материал из wiki.sipnet.ru
Перейти к: навигация, поиск

Как формируются поля заголовка и тип скачиваемого файла

Если пароля нет

Response.ContentType:='audio/mpeg'

Если в запросе указать параметр save=1 то

Response.ContentType:='application/octet-stream';
Response.CustomHeaders.Add('Content-Disposition=attachment; filename='+DName+'.mp3');

Если при настройке записи клиент указа пароль шифрования

Response.ContentType:='application/x-zip-compressed';

Если в запросе указать параметр save=1 то

Response.ContentType:='application/octet-stream';
Response.CustomHeaders.Add('Content-Disposition=attachment; filename='+DName+'.zip');

Скачивание в одну нитку

Этот пример позволяет скачать несколько свежих записей, им можно скачивать и много записай, но это займет очень много времени Все необходимые пояснения даны в текстах комментариев.


#!/usr/bin/env python3
import shutil
import requests
import datetime

# Это переменные для запроса звонков и их записей. см. Описание тут https://wiki.sipnet.ru/index.php?title=API_для_интеграции_с_CRM
payload = {'operation': 'calls',      # Метод который возвращает статистику звонков и ссылки на записи.
           'D1': '00/00/2000',        # Если не правильная дата, то сегодня
           'D2': '00/00/2000',        # Если не правильная дата, то сегодня
           'sipuid': '<Login>',       # Тут логин или SIP-ID укажите
           'password': '<Password>',  # Тут конечно пароль нужен
           'format': '2'              # Это формат возвращаемых данных. Нам очень Json понравился
           }

# Это URL запроса статистики
url = 'https://api.sipnet.ru/cgi-bin/Exchange.dll/sip_balance'

# Теперь определим лимит числа скачиваемых файлов. Если это Maxgetfiles=0, то файлы не скачиваются
Maxgetfiles = 10

response= requests.post(url, data=payload)

if response.status_code == requests.codes.ok:
    dictionary=response.json()
    del response
    if dictionary["Result"]:
        # нам уже доступна структура данных ответа. Если хотите, напечатайте ее.
        # print ("Структура ответа ", dictionary.keys())
        if 'calls' in dictionary.keys():
            # нам уже доступна структура данных самого звонка. Если хотите, напечатайте ее.
            # print ("Структура звонков ", dictionary["calls"][1].keys())
            # print ("Структура [1] ", dictionary["calls"][1])
            # Далее цикл для обхода всех полученых звонков и печати отчета по ним.
            # Для вывода звонков от начала дня к текущему моменту
            # for i in dictionary["calls"]:
            for i in reversed(dictionary["calls"]):
                if 'phone' in i.keys():
                    print ("======================================================================================================")
                    print (i["cid"], '',"Дата= " ,i["gmt"],"Номер= ",i["phone"], "АОН= ", i["cli"], "Длительность= ", i["duration"])
                    print (str(datetime.datetime.utcnow()))
                else:
                    print ("Странный звонок у него нет номера B")
                if 'url' in i.keys():
                    # Это URL файла с записью разговора.
                    print (i["url"])
                    # Проверяем, не исчерпан ли лимит скачивания файлов
                    if Maxgetfiles>0:
                       # Скачаем и сохраним все обнаруженные записи имя сохраненного файла состоит из cid звонка.
                       response = requests.get(i["url"], stream=True)
                       if response.status_code == requests.codes.ok:
                           FileName = str(i["gmt"])+"_"+str(i["phone"])
                           if response.headers['Content-Type'] == 'audio/mpeg':
                               FileName = FileName+".mp3"
                           else:
                               FileName = FileName+".zip"
                           FileName = FileName.replace('/', '-').replace(':', '-')
                           with open(FileName, 'wb') as out_file:
                               shutil.copyfileobj(response.raw, out_file)
                           del response
                           Maxgetfiles -= 1
                       else:
                           print ("Запись не скачалась. Получили код ", response.status_code)
                    else:
                        print ("Лимит скачивания исчерпан")
                        break
                else:
                    print ("Нет MP3 записи этого звонка")
        else:
            print ("Результат нормальный, но Нет звонков")
    else:
        print ("Что-то пошло не так. Плохой результат получили ", dictionary["Result"])

else:
    print ("Совсем плохо. Получили код ", response.status_code)

Многопоточное скачивание больших массивов

Это пример немного сложнее, но зато позволяет скачать около 1500 записей за пару минут.

#!/usr/bin/env python3
import shutil
import requests
import datetime
from multiprocessing import Pool

# Это переменные для запроса звонков и их записей. см. Описание тут https://wiki.sipnet.ru/index.php?title=API_для_интеграции_с_CRM
payload = {'operation': 'calls',      # Метод который возвращает статистику звонков и ссылки на записи.
           'D1': '00',        # Если не правильная дата, то сегодня
           'D2': '00',        # Если не правильная дата, то сегодня
           'sipuid': '<SIPID>',       # Тут логин или SIP-ID укажите
           'password': '<Password>',  # Тут конечно пароль нужен
           'format': '2'              # Это формат возвращаемых данных. Нам очень Json понравился
           }

# Это URL запроса статистики
url = 'https://api.sipnet.ru/cgi-bin/Exchange.dll/sip_balance'

# Теперь определим лимит числа скачиваемых файлов. Если это Maxgetfiles=0, то файлы не скачиваются
# Не работает в многопотоковом варианте.
#Maxgetfiles = 10

# Описываем процедуру скачивания записи разговора
def create_MP3file(callinfo):
    if 'phone' in callinfo.keys():
        print ("======================================================================================================")
        print (callinfo["cid"], '',"Дата= " ,callinfo["gmt"],"Номер= ",callinfo["phone"], "АОН= ", callinfo["cli"], "Длительность= ", callinfo["duration"])
        print ("Время в момент скачивания файла: ", str(datetime.datetime.utcnow()))
        if 'url' in callinfo.keys():
           # Это URL файла с записью разговора.
           print (callinfo["url"])
           # Скачаем и сохраним все обнаруженные записи имя сохраненного файла состоит из cid звонка.
           response = requests.get(callinfo["url"], stream=True)
           if response.status_code == requests.codes.ok:
               FileName = str(callinfo["gmt"])+"_"+str(callinfo["phone"])
               if response.headers['Content-Type'] == 'audio/mpeg':
                   FileName = FileName+".mp3"
               else:
                   FileName = FileName+".zip"
               FileName = FileName.replace('/', '-').replace(':', '-')
               with open(FileName, 'wb') as out_file:
                   shutil.copyfileobj(response.raw, out_file)
               del response
           else:
               print ("Запись не скачалась. Получили код ", response.status_code)
        else:
            print ("Нет MP3 записи этого звонка")
    else:
        print ("Странный звонок у него нет номера B")

# Это основной метод, который получает список звонков и запускает многопотоковое скачивание
if __name__ == '__main__':
    print ("Начало исполнения: ", str(datetime.datetime.utcnow()))
    # Это создание пула исполнителей, которые будут скачивать записи
    # Число исполнителей нужно выбирать под компьютер, на котором выполняется. У меня 1500 записей скачались менее чем за 2 минуты
    pool = Pool(10)
    # Запрос статистики со ссылками на файлы записи разговоров
    response = requests.post(url, data=payload)
    if response.status_code == requests.codes.ok:
        dictionary=response.json()
        del response
        # Начинаем анализ того, что получили
        if dictionary["Result"]:
            # нам уже доступна структура данных ответа. Если хотите, напечатайте ее.
            # print ("Структура ответа ", dictionary.keys())
            if 'calls' in dictionary.keys():
                # нам уже доступна структура данных самого звонка. Если хотите, напечатайте ее.
                # print ("Структура звонков ", dictionary["calls"][1].keys())
                # print ("Структура [1] ", dictionary["calls"][1])
                # Далее запуск массового многопоточного скачивания записей всех полученых звонков.
                pool.map(create_MP3file, dictionary["calls"])
                pool.close()
                pool.join()
            else:
                print ("Результат нормальный, но Нет звонков")
        else:
            print ("Что-то пошло не так. Плохой результат получили ", dictionary["Result"])
    else:
        print ("Совсем плохо. Получили код ", response.status_code)
    # Печатаем время завершения работы и выходим.
    print ("Конец исполнения: ", str(datetime.datetime.utcnow()))


Пример скрипта для скачивания файлов с записями разговоров на стороне третьих сервиспровайдеров

Записи разговоров нужны не только для доказательства правоты и "на всякий случай". Бывает необходимо анализировать разговоры и их качество на регулярной основе.

Конечно, прослушивать разговоры может ответственный сотрудник, но гораздо интереснее когда разговоры анализируются специальными аналитическими центрами. Так можно выявить гораздо больше проблем и вовремя принять меры для улучшения работы вашей команды.

На пути реализации такой интеграции с аналитическим службами возникает проблема с безопасностью. Для работы предыдущих скриптов требуется логин и пароль от аккаунтов, а передавать их третьей стороне крайне не желательно.

Ниже приведем пример кода скрипта, который авторизуется не через логин и пароль, а через, специально для этого предназначенный, ключ API.

#!/usr/bin/env python3
import shutil
import requests
import datetime as dt

# Это переменные для запроса звонков и их записей. см. описание по ссылкам ниже
# https://newapi.sipnet.ru/apidoc.pdf (Ранее https://wiki.sipnet.ru/index.php?title=API_для_интеграции_с_CRM)
# URL основной операции имеет вид https://newapi.sipnet.ru/api.php?operation=getrec& apikey= 

# Определим лимит числа скачиваемых файлов. Если это Maxgetfiles=0, то файлы не скачиваются
Maxgetfiles = 10

# Это URL запроса статистики и его основные параметры
URL = 'https://newapi.sipnet.ru/api.php'

# Создадим массив с параметрами запроса.
payload = {'operation': 'calls',   # Метод который возвращает статистику звонков и ссылки на записи.
           'apikey': 'fdde2154-4ca5-4ad8-7de3-07affa5c4ca3',   # Ключ авторизации по API получить в панели администратора ВАТС.
           'showchild': '1',       # Если указан 1 то звонки выводятся и с дочерних аккаунтов.
           'D1': '01-02-2019',     # Если не правильная дата, то сегодня
           'D2': '03-02-2019',     # Если не правильная дата, то сегодня
           'format': 'json'        # Это формат возвращаемых данных. Нам очень Json понравился
           }

# Напечатаем исходные данные, на всякий случай.
print("===============================================")
print(URL)
print(payload)
print(Maxgetfiles)
print("===============================================")

# Запрашиваем статистику звонков и начинаем разбор полученного.
response= requests.post(URL, data=payload)

if response.status_code == requests.codes.ok:
    dictionary=response.json()
    # нам уже доступна структура данных ответа. Если хотите, напечатайте ее.
    # print ("Структура ответа ", dictionary.keys())

    del response
    if dictionary["status"] != 'error':
        if 'calls' in dictionary.keys():
            # нам уже доступна структура данных самого звонка. Если хотите, напечатайте ее.
            # print ("Структура звонков ", dictionary["calls"][1].keys())
            # print ("Структура [1] ", dictionary["calls"][1])
            # Далее цикл для обхода всех полученных звонков и печати отчета по ним.
            # Статистика обрабатывается от момента запроса к началу дня
            # Для вывода звонков от начала дня к текущему моменту
            # for i in dictionary["calls"]:
            for i in reversed(dictionary["calls"]):
                if 'Phone' in i.keys():
                    print ("======================================================================================================")
                    print (i["CID"], '', i["Account"], '', i['Direction'], '\n', "Дата= " , i["GMT"], "Номер= ", i["Phone"], "АОН= ", i["CLI"], "Длительность= ", i["Duration"])
                else:
                    print ("Странный звонок у него нет номера B")
                if 'URL' in i.keys():
                    # Обнаружен URL файла с записью разговора.
                    print (i["URL"])
                    # Проверяем, не исчерпан ли лимит скачивания файлов
                    if Maxgetfiles>0:
                       # Скачаем и сохраним все обнаруженные записи имя сохраненного файла состоит из cid звонка.
                        response = requests.get(i["URL"], stream=True)
                        if response.status_code == requests.codes.ok:
                            # Тут мы формируем имя файла записи разговора, данные берем из массива с описанием параметров звонка
                            FileName = str(int(dt.datetime.strptime(i["GMT"], '%d.%m.%Y %H:%M:%S').timestamp()))+"_"+i["CLI"]+"_"+i["Phone"]+"_"+i['Direction']
                            # Определяем тип скаченного файла и выбираем нужное расширение имени файла
                            if response.headers['Content-Type'] == 'audio/mpeg':
                                FileName = FileName+".mp3"
                            else:
                                FileName = FileName+".zip"
                            FileName = FileName.replace('/', '-').replace(':', '-')
                            # Сохраняем скаченный файл с нужным именем.
                            with open(FileName, 'wb') as out_file:
                                shutil.copyfileobj(response.raw, out_file)
                            del response
                            Maxgetfiles -= 1
                        else:
                            print ("Запись не скачалась. Получили код ", response.status_code)
                    else:
                        print ("Лимит скачивания исчерпан")
                        break
                else:
                    print ("Нет MP3 записи этого звонка")
        else:
            print ("Результат нормальный, но Нет звонков")
    else:
        print ("Что-то пошло не так. Плохой результат получили ")
        print ("Статус ответа ", dictionary["status"])
        print ("Ошибка ", dictionary["errorCode"], dictionary["errorMessage"])       
else:
    print ("Совсем плохо. Получили код ", response.status_code)