четверг, 13 марта 2014 г.

Python: практика в конвертации логов АТС

Некоторые операторы телефонной связи любят присылать статистику звонков в формате крайне неудобном для обработки компьютером. Приходится с ними бороться, просить присылать структурированные файлы и придумывать свои обработчики для той информации, что они прислали. Порой быстрее самому сделать обработчик, нежели добиться пока менеджер захочет донести информацию до инженерно-технического персонала с целью получить логи АТС в чистом виде. Некоторые телекоммуникационные гиганты убеждали меня несколько месяцев, что получить логи в другом виде НЕВОЗМОЖНО! Несмотря на то, что эта же самая компания в соседнем регионе любезно присылает все как надо, без криков, споров и проблем. Видима связка между первой и второй линией суппорта сильно ограниченная.

Пока решаются организационные вопросы встала задача импортировать логи звонков в базу за 2013 год. Оператор прислали за каждый месяц по файлику.
Такой вот формат. Для визуальной обработки данных вполне подходит, но за один месяц данных на 20 тыс строк и это только по одному оператору. Вряд ли кто-то в здравом уме будет обрабатывать это вручную. Для импорта в базу данных необходимо подготовить исходный файл, т.е. изменить вид таблицы. Альтернативный способ - интеллектуальный импорт, т.е. парсить файл непосредственно во время импорта.
При имеющемся готовом решении импорта данных в базу структурированных файлов, остановился на первом способе - переконвертировать файл. Итак в файле у меня есть все данные: абонент, номер вызова, дата и время вызова, длительность и стоимость вызова. Неудобство в том, что номер абонента не в каждой строке, а обозначен в начале блока строк со звонками по датам в течении месяца. В конце блока итоговые значения, суммы. Все это нам не очень интересно. Необходимо вписать в каждую строку с данными о звонке - номер абонента (т.е. номер звонящего).
Для решения задачи решил попрактиковаться на Питоне (Python). Как раз накануне знакомился с этим языком и искал ему практическое применение. Отрабатываю открытие-закрытие файла и обработка данных с созданием новой структуры. Обработка сделана для всех файлов за год.

__author__ = 'patriot'
# coding: cp1251
 
def pars_file(fname):
    print(fname)
 
    f = open(fname+fcsv, 'r')
    abon = 'Абонентский номер:'
    nonum = 'nonenum'
 
    ofname = fname+'out'+fcsv
    print(ofname)
 
    of = open(ofname, 'w')
 
    for line in f :
        line.decode('cp1251')
        sline = line.split(';')
        if sline[0].startswith('['):
            sline[0] = sline[0][2:]
        sline[0] = sline[0].strip()
        if sline[0].startswith(abon):
            vnum = sline[0][-10:]
        if sline[0][0:1].isdigit() and sline[0][2]=='.' and sline[2][0:1].isdigit():
            sline.insert(0,vnum)
        else:
            sline.insert(0,nonum)
        oline = ';'.join(sline)
        of.write(oline)
 
    f.close()
    of.close()
 
fyear = '13'
fcsv = '.csv'
mounths = ['01','02','03','04','05','06','07','08', '09', '10','11','12']
for i in mounths:
    filename = '2013/'+i + fyear
    print(filename)
    pars_file(filename)


В результате получаем файл в таком виде:

  Для того чтобы было проще в дальнейшем отсекать лишние строки использую поле "nonenum", по большому счету нужно для проверки правильности работы скрипта, если ошибок не выявится, то можно такие строки не вставлять в новый файл, тем самым получить результат в чистом виде.
Во время решения пришлось немного покопаться с кодировками, т.к. исходный файл был в кодировке cp1251 (windows, Кирилица), не сразу получилось отслеживать промежуточные результаты в консоли интерпретатора. Основная идея скрипта, находить нужную строку с номером абонента, вырезать из нее номер и вставлять этот номер во все последующие строки с данными о звонках с этого номера. Также пришлось проверить и чистить некоторые поля от мусора (лишние символы, пробелы).

Комментариев нет:

Отправить комментарий