# -*- coding : utf-8 -*- import os import re import json import glob import time import base64 import datetime import operator import requests import logging import traceback import threading import numpy as np import tornado.web import tornado.ioloop import tornado.options import tornado.httpserver from urllib import parse from urllib import request from scipy.io import wavfile from pydub import AudioSegment # from sphfile import SPHFile from tornado.web import RequestHandler from tornado.options import define, options from openpyxl import Workbook, load_workbook import rule import jiaoyu import gaotu_rule import jingka_rule import meituan_rule import fandeng_rule import caishang_rule port = 9501 wav_dir = './wav_dir' cookie_format = 'Hm_lvt_156e9eafdaa2e262ed04972cb49e11a1=1621319206; ' \ 'isDataPageEnabled=false; isRandomPhonelineEnabeld=true; ' \ 'isTTSMediaEnabled=true; isEarlyMediaRecEnabled=false; ' \ 'isEarlyMediaRecObEnabled=false; isDeflectEnabled=false; ' \ 'isRobotFeeVisible=true; isAlipayEnabled=false; alipayRechargePriceMin=10000; ' \ 'isEarlyMediaRecorded=false; isManualCampaignEnabled=false; effectiveDuration=0; '\ 'isScriptEnabled=false; isCallCenterEnabled=true; isRobotEnabled=false; ' \ 'isVoiceSiteCopyEnabled=false; isAutoCampaignEnabled=false; ' \ 'isRepairOpenEnabled=false; isRandomPhonelineUpdatedEnabled=true; ' \ 'isCallBlockingEnabled=true; isReceiptEnabled=true; ' \ 'salesName=%E7%A8%8B%E4%B8%AD%E5%8D%8E; isTeamNumberPoolEnabled=false; ' \ 'isAgentPhonelineEnabled=false; isRecordDownLoadEnabled=true; ' \ 'incrAgentEnabled=true; isDeleteRecordEnabled=false; isTranscriptionEnabled=false; ' \ 'isSupervisorCallEnabled=true; constantlyInspect=false; fifoType=1; ' \ 'callStartTime=08%3A00; callEndTime=21%3A00; teamVgwEnabled=true; ' \ 'systemLogSearchEnabled=false; isCampaignEarlyMediaRecorded=false; ' \ 'orgIntelligentRoutingEnabled=false; ' \ 'Hm_lpvt_156e9eafdaa2e262ed04972cb49e11a1={}; z=23jder; ' \ 'token={}; mobile=13552201923; ' \ 'agentLimit=360; orgId={}; ' \ 'orgName={}; ' \ 'userId=739606; isPartner=false; isIvrEnabled=false; isFifoEnabled=true; ' \ 'isVccEnabled=false; channelLimit=1; agentPrice=500000; ' \ 'channelPrice=0; isSmsEnabled=false; smsPrice=800; ' \ 'contactPhone=18868832064; fifoAgentLimit=360' headers = { 'Host': 'cfg.duyansoft.com', 'Accept': 'application/json, text/plain, */*', 'Accept-Encoding': 'gzip, deflate, br', 'Accept-Language': 'zh-CN,zh;q=0.9', 'Connection': 'keep-alive', 'sec-ch-ua': '"Google Chrome";v="89", "Chromium";v="89", ";Not A Brand";v="99"', 'Referer': 'https://cfg.duyansoft.com/cloud/phoneRecord', 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36', 'Cookie': '' } class Chat_record(object): def __init__(self, content, start_time, end_time, role, result_id): self.content = content self.start_time = start_time self.end_time = end_time self.role = role self.result_id = result_id self.webhook = 'https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=25ea61a4-35b8-4ca3-9e8a-527136a9a367' self.webhook_token = 'https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=cfc9a7ec-fae4-4802-9844-caae493e5ab4' def add_legal(self, legal_type, detail): self.legal = False self.legal_type = legal_type self.detail = detail class Quality_test( RequestHandler ): def download_to_wav(self, url, id, ip): response = requests.get(url) if not os.path.exists(wav_dir): os.mkdir(wav_dir) if url[-3:] == 'wav': self.file_path = '{}/{}_{}.wav'.format(wav_dir, ip, id) self.file_path_human = '' with open(self.file_path, 'wb') as fp: fp.write(response.content) fp.flush() elif url[-3:] == 'mp3': self.file_path = '{}/{}_{}.mp3'.format(wav_dir, ip, id) self.file_path_human = '' with open(self.file_path, 'wb') as fp: fp.write(response.content) fp.flush() # song = AudioSegment.from_mp3(self.file_path) # c = 'wget "{}" -c -T 10 -t 10 -O "{}"'.format(url, self.file_path) # os.system(c) c = 'ffmpeg -i "{}" -f wav "{}"'.format(self.file_path, self.file_path[:-3]+'wav') os.system(c) os.remove( self.file_path ) self.file_path = '{}/{}_{}.wav'.format(wav_dir, ip, id) # song.export( self.file_path, format='wav' ) elif url.split('?')[0].split('/')[-1][-3:] == 'mp3': self.file_path = '{}/{}_{}.mp3'.format(wav_dir, ip, id) self.file_path_human = '' c = 'wget "{}" -c -T 10 -t 10 -O "{}"'.format(url, self.file_path) os.system(c) c = 'ffmpeg -i "{}" -f wav "{}"'.format(self.file_path, self.file_path[:-3]+'wav') os.system(c) os.remove( self.file_path ) self.file_path = self.file_path[:-3]+'wav' elif url.split('?')[0].split('/')[-1][-4:] == 'flac': self.file_path = '{}/{}_{}.flac'.format(wav_dir, ip, id) self.file_path_human = '' c = 'wget "{}" -c -T 10 -t 10 -O "{}"'.format(url, self.file_path) os.system(c) c = 'ffmpeg -i "{}" -f wav "{}"'.format(self.file_path, self.file_path[:-4]+'wav') os.system(c) os.remove( self.file_path ) self.file_path = self.file_path[:-4]+'wav' elif url.split('?')[0].split('/')[-1][-3:] == 'wav': self.file_path = '{}/{}_{}.wav'.format(wav_dir, ip, id) self.file_path_human = '' with open(self.file_path, 'wb') as fp: fp.write(response.content) fp.flush() else: send_wechat_warning(id, ip, '音频格式错误') self.write(u'音频格式报警') def get_human_port_from(self, answer_time, transfer_time): song = AudioSegment.from_wav(self.file_path) answer_time = datetime.datetime.strptime(answer_time, "%Y-%m-%d %H:%M:%S") transfer_time = datetime.datetime.strptime(transfer_time, "%Y-%m-%d %H:%M:%S") robot_part = transfer_time - answer_time human_part = song[robot_part.seconds*1000:] self.file_path_human = self.file_path[:-4] + '_human' + '.wav' human_part.export(self.file_path_human, format='wav') def asr_audio(self, path): url = 'http://192.168.1.125:8010/v1/asr' with open(path, 'rb') as f: encoded = base64.b64encode(f.read()).decode('utf8') headers = {'Content-Type': 'application/json'} data = {"audio_data": encoded} try: response = requests.post(url, data=json.dumps(data), headers=headers) result_text = json.loads(response.text) if 'result' in result_text: results = result_text['result'] else: results = [] return results except Exception as ee: import traceback traceback.print_exc() return [] def fix_channel(self, left_result, right_result, sign_change_channel): pattern = re.compile(r'工号|客服经理|客户经理|(您的|你的).{0,10}顾问|为您.{0,10}服务') target = '' for right in right_result[:]: target += right['result'] result = pattern.search(target) if result or sign_change_channel: return right_result, left_result, 1 return left_result, right_result, 0 def convert_to_record(self, results, role, result_id, time, call_duration): records = [] for result in results: content = result['result'] # start_time = result['start_time'] minute, second = result['start_time'].split(':') minute = int(minute) * 60 second = int(second.split('.')[0]) start_time = minute + second# - call_front # end_time = result['end_time'] minute, second = result['end_time'].split(':') minute = int(minute) * 60 second = int(second.split('.')[0]) end_time = minute + second# - call_front record = Chat_record(content, start_time, end_time, role, result_id) records.append(record) return records def sort_records(self, chat_records): cmpfun = operator.attrgetter('start_time') chat_records.sort(key=cmpfun) return chat_records def sample_from_file(self, file_path): try: samplerate, data = wavfile.read(file_path) except Exception: try: c = 'ffmpeg -i "{}" "{}"'.format(file_path, file_path) os.system(c) samplerate, data = wavfile.read(file_path) except Exception: traceback.print_exc() os.remove( file_path ) return 0, 0, 0 time = data.shape[0] // samplerate return samplerate, data, time def get_content(self, id, call_duration): samplerate, data, time = self.sample_from_file(self.file_path) if samplerate == 0 and data == 0: return 0, 0, 0, 0 # if company == 'jiaoyu' and time < 60: # os.remove( self.file_path ) # return 0, 0, 0, 0 left = [] right = [] if len(data.shape) == 2: for item in data: left.append(item[0]) right.append(item[1]) self.file_path_left = self.file_path[:-4] + '_left.wav' self.file_path_right = self.file_path[:-4] + '_right.wav' wavfile.write(self.file_path_left, samplerate, np.array(left)) wavfile.write(self.file_path_right, samplerate, np.array(right)) left_result = self.asr_audio(self.file_path_left) right_result = self.asr_audio(self.file_path_right) left_result, right_result, sign_change_channel = self.fix_channel( left_result, right_result, 0 ) # os.remove(self.file_path) os.remove(self.file_path_left) os.remove(self.file_path_right) if self.file_path_human: samplerate, data, time = self.sample_from_file(self.file_path_human) if samplerate == 0 and data == 0: return 0, 0, 0, 0 for item in data: left.append(item[0]) right.append(item[1]) self.file_path_left = self.file_path_human[:-4] + '_left.wav' self.file_path_right = self.file_path_human[:-4] + '_right.wav' wavfile.write(self.file_path_left, samplerate, np.array(left)) wavfile.write(self.file_path_right, samplerate, np.array(right)) left_result = self.asr_audio(self.file_path_left) right_result = self.asr_audio(self.file_path_right) left_result, right_result, sign_change_channel = self.fix_channel(left_result, right_result, sign_change_channel) os.remove( self.file_path_human ) os.remove( self.file_path_left ) os.remove( self.file_path_right ) left_record = self.convert_to_record(left_result, 'staff', id, time, call_duration) right_record = self.convert_to_record(right_result, 'user', id, time, call_duration) right_record.extend(left_record) right_record = self.sort_records(right_record) return right_record, time, 2, 1 else: result = self.asr_audio(self.file_path) record = self.convert_to_record(result, 'staff', id, time, call_duration) os.remove( self.file_path ) return record, time, 1, 1 def send_back(self, ip, customer_id, sign): sign = '不合格' if sign else '合格' try: response = requests.get('http://39.98.54.147:8005/writeBack?ip={}&customerId={}&checkResult={}'.format(ip, customer_id, sign)) except Exception: traceback.print_exc() send_wechat_warning(customer_id, ip, '转发服务请求失败') self.write(u'转发服务请求失败') def record_all(self, args): ip = args[0] date = '{}-{}-{}'.format(datetime.datetime.now().year, datetime.datetime.now().month, datetime.datetime.now().day) if not os.path.exists('./{}_data_dir/{}_反馈客户数据.xlsx'.format(ip, date)): fp = open('./{}_data_dir/{}_反馈客户数据.xlsx'.format(ip, date), 'w') if len(args) == 5: fp.write('质检结果\t客服ID\t电话开始时间\t外拨坐席\n') else: fp.write('质检结果\t客服ID\t电话开始时间\t通话时长\t外拨职场\t外拨小组\t外拨坐席\n') else: fp = open('./{}_data_dir/{}_反馈客户数据.xlsx'.format(ip, date), 'a') if len(args) == 5: ip, sign, customer_id, call_date, name = args fp.write('{}\t{}\t{}\t{}\n'.format(sign, customer_id, call_date, name)) else: ip, sign, customer_id, call_date, time, call_place, call_group, name = args fp.write('{}\t{}\t{}\t{}\t{}\t{}\t{}\n'.format(sign, customer_id, call_date, time, call_place, call_group, name)) fp.close() def record_jingka(self, ip, args, sign): date = '{}-{}-{}'.format(datetime.datetime.now().year, datetime.datetime.now().month, datetime.datetime.now().day) if not os.path.exists('./{}_data_dir/{}_反馈客户数据.xlsx'.format(ip, date)): fp = open('./{}_data_dir/{}_反馈客户数据.xlsx'.format(ip, date), 'w') fp.write('监听日期\t成交情况\t京东用户名\t话单ID\t振玲开始时间\t振玲结束时间\t客户ID\t' '电话开始时间\t电话结束时间\t通话时长\t是否接通\t外拨职场\t外拨小组\t外拨坐席\t' '备注内容\t是否合格\n') else: fp = open('./{}_data_dir/{}_反馈客户数据.xlsx'.format(ip, date), 'a') final_str = '' for i in range(len(args)): final_str += args[i] + '\t' final_str += '无\t{}\n'.format('不合格' if sign else '合格') fp.write(final_str) fp.close() def optimize_record(self, chat_record, company): last_time = '' stop_sign = False result_sign = False content_list = list() pattern = re.compile(r'(^((?!.).)*对+(,|。)*((?!.).)*$)') # 获取重合音频时间段 start_time = 0 end_time = 0 user_start_time = 0 user_end_time = 0 repeat_time = list() for c in chat_record: if c.content not in [',', '正在呼叫请稍候,']: result = pattern.search(c.content) if result: if c.content.startswith('1'): if stop_sign and c.start < last_time: result_sign = True else: stop_sign = True last_time = c.end_time else: c.content = c.content.replace(',', '') if c.role != 'staff': # 判断到不同的角色时,开始计算是否有重复时长 if end_time < c.start_time: if c.start_time > start_time and end_time > c.end_time: # repeat_time += c.end_time - c.start_time repeat_time.append(c.end_time - c.start_time) elif c.start_time > start_time and c.end_time > end_time: # repeat_time += end_time - c.start_time repeat_time.append(end_time - c.start_time) user_start_time = c.start_time user_end_time = c.end_time else: if user_end_time > c.start_time: if user_end_time > c.end_time: # repeat_time += user_end_time - c.start_time repeat_time.append(user_end_time - c.start_time) elif user_end_time > c.end_time: # repeat_time += c.end_time - c.start_time repeat_time.append(c.end_time - c.start_time) start_time = c.start_time end_time = c.end_time if company in ['jiaoyu', 'fandeng', 'caishang']: content_list.append([c.content, 0 if c.role == 'staff' else 1, c.start_time, c.end_time]) elif company == 'meituan': content_list.append([c.content, 0 if c.role == 'staff' else 1, c.start_time, c.end_time]) else: content_list.append([c.content, 1 if c.role == 'staff' else 0, c.start_time, c.end_time]) return content_list, result_sign, repeat_time def task(self, **kwargs): # ip, call_id, customer_id, name, call_date, wav_path): # print( 'key value :{}'.format(kwargs) ) ip = kwargs.get('ip', '') call_id = kwargs.get('call_id', '') # 唯一标示 customer_id = kwargs.get('customer_id', '') company = kwargs.get('company', '') name = kwargs.get('name', '') phone = kwargs.get('phone', '') wav_path = kwargs.get('wav_path', '') call_date = kwargs.get('call_date', '') call_place = kwargs.get('call_place', '') call_group = kwargs.get('call_group', '') call_answer = kwargs.get('call_answer', '') call_transfer = kwargs.get('call_transfer', '') call_duration = kwargs.get('call_duration', '') self.download_to_wav(wav_path, call_id, ip) wav_path = 'http://114.242.9.19:9502/wav_dir/{}_{}.wav'.format(ip, call_id) # self.file_path = './wav_dir/20211009173337525430-111290_6634bdd19f7b4d30ba26608289aa5263_17_33_53.wav' if call_transfer: self.get_human_port_from(call_answer, call_transfer) chat_record, time, channel, sign = self.get_content(call_id, call_duration) if not sign: return 0 content_list, stop_sign, repeat_time = self.optimize_record(chat_record, company) if company == 'jiaoyu': sign = gaotu_rule.recognition(content_list, repeat_time, call_id, customer_id, name, call_date, wav_path, ip, time, channel, phone, stop_sign) self.record_all([ip, sign, customer_id, call_date, name]) elif company == 'fandeng': sign = fandeng_rule.recognition(content_list, repeat_time, call_id, customer_id, name, call_date, wav_path, ip, time, channel, phone, stop_sign) self.record_all([ip, sign, customer_id, call_date, name]) elif company == 'caishang': sign = caishang_rule.recognition(content_list, repeat_time, call_id, customer_id, name, call_date, wav_path, ip, time, channel, phone, stop_sign) self.record_all([ip, sign, customer_id, call_date, name]) elif company == 'meituan': sign = meituan_rule.recognition(content_list, repeat_time, call_id, customer_id, name, call_date, wav_path, ip, time, channel, phone, stop_sign) self.record_all([ip, sign, customer_id, call_date, time, call_place, call_group, name]) else: if company == 'jingka': sign = jingka_rule.recognition(content_list, repeat_time, call_id, customer_id, name, call_date, wav_path, ip, time, channel, stop_sign, call_answer) else: sign = rule.recognition(content_list, repeat_time, call_id, customer_id, name, call_date, wav_path, ip, time, channel, stop_sign) if len(ip.split('.')) == 4: self.send_back(ip, customer_id, sign) else: self.record_all([ip, sign, customer_id, call_date, time, call_place, call_group, name]) def get(self): ip = self.get_argument('ip', '') name = self.get_argument('displayName', '') company = self.get_argument('company', '') call_id = self.get_argument('callId', '') customer_id = self.get_argument('customerId', '') phone = self.get_argument('phone', '') wav_path = self.get_argument('wavPath', '') call_date = self.get_argument('callDate', '') call_answer = self.get_argument('answerDate', '') call_transfer = self.get_argument('transferDate', '') call_duration = self.get_argument('callDuration', '') processed = self.get_argument('processed', '') call_place = self.get_argument('call_place', '') call_group = self.get_argument('call_group', '') if company in ['jiaoyu', 'fandeng', 'caishang']: # self.task(company=company, ip=ip, call_id=call_id, customer_id=customer_id, name=name, call_date=call_date, call_place='', call_group='', phone=phone, wav_path=wav_path) p = threading.Thread(target=self.task, kwargs=( {'company': company, 'ip': ip, 'call_id': call_id, 'customer_id': customer_id, 'name': name, 'call_date': call_date, 'call_answer': call_answer, 'call_transfer': call_transfer, 'call_place': call_place, 'call_group': call_group, 'phone': phone, 'wav_path': wav_path, 'call_duration': call_duration})) p.start() elif company == 'meituan': # self.task(company=company, ip=ip, call_id=call_id, customer_id=customer_id, name=name, call_date=call_date, call_place='', call_group='', phone=phone, wav_path=wav_path) p = threading.Thread(target=self.task, kwargs=( {'company': company, 'ip': ip, 'call_id': call_id, 'customer_id': customer_id, 'name': name, 'call_date': call_date, 'call_answer': call_answer, 'call_transfer': call_transfer, 'call_place': call_place, 'call_group': call_group, 'phone': phone, 'wav_path': wav_path, 'call_duration': call_duration})) p.start() else: if processed == '1': wb = Workbook() ws = wb.active ws.append([call_id, customer_id, name, call_date, wav_path, '已质检']) if not os.path.exists('./{}_data_dir/'.format(ip)): os.mkdir('./{}_data_dir/'.format(ip)) date = '{}-{}-{}'.format(datetime.datetime.now().year, datetime.datetime.now().month, datetime.datetime.now().day) if glob.glob('./{}_data_dir/*.xlsx'.format(ip)) and not glob.glob('./{}_data_dir/*.xlsx'.format(ip))[-1].split('/')[-1].startswith(date): for file_path in glob.glob('./{}_data_dir/*.xlsx'.format(ip)): os.remove(file_path) wb.save( './{}_data_dir/'.format(ip) + '{}_{}_{}_{}.xlsx'.format(date, call_id, 0, 0) ) else: fid = 'fid=' + self.get_argument('fid', '') if self.get_argument('fid', '') else '' token = 'token=' + self.get_argument('token', '') if self.get_argument('token', '') else '' filename = 'filename=' + self.get_argument('filename', '') if self.get_argument('filename', '') else '' expires = 'Expires=' + self.get_argument('Expires', '') if self.get_argument('Expires', '') else '' signature = 'Signature=' + self.get_argument('Signature', '') if self.get_argument('Signature', '') else '' if len(ip.split('.')) != 4: pass # wav_path = wav_path.replace('wav', 'mp3') elif fid and token and filename: wav_path = '&'.join([wav_path, fid, token, filename]) elif expires and signature: wav_path = '&'.join([wav_path, expires, parse.quote(signature)]) else: # 音频格式报警 send_wechat_warning(customer_id, ip, '音频格式错误') self.write(u'音频格式报警') # print('==========================') # print(wav_path, expries, parse.quote(signature)) # self.task(company=company, ip=ip, call_id=call_id, customer_id=customer_id, name=name, call_date=call_date, # call_answer=call_answer, call_transfer=call_transfer, # call_place=call_place, call_group=call_group, phone=phone, wav_path=wav_path, call_duration=call_duration) p = threading.Thread(target=self.task, kwargs=( {'company': company, 'ip': ip, 'call_id': call_id, 'customer_id': customer_id, 'name': name, 'call_date': call_date, 'call_answer': call_answer, 'call_transfer': call_transfer, 'call_place': call_place, 'call_group': call_group, 'phone': phone, 'wav_path': wav_path, 'call_duration': call_duration})) p.start() self.write('success') class Meituan_Quality_test( RequestHandler ): def asr_audio(self, path): url = 'http://192.168.1.125:8010/v1/asr' with open(path, 'rb') as f: encoded = base64.b64encode(f.read()).decode('utf8') headers = {'Content-Type': 'application/json'} data = {"audio_data": encoded} try: response = requests.post(url, data=json.dumps(data), headers=headers) result_text = json.loads(response.text) if 'result' in result_text: results = result_text['result'] else: results = [] return results except Exception as ee: import traceback traceback.print_exc() return [] def fix_channel(self, left_result, right_result, sign_change_channel): pattern = re.compile(r'(京东|金融|客户|客服|经理).*工号') target = '' for right in right_result[:]: target += right['result'] result = pattern.search(target) if result or sign_change_channel: return right_result, left_result, 1 return left_result, right_result, 0 def convert_to_record(self, results, role, result_id): records = [] for result in results: content = result['result'] start_time = result['start_time'] end_time = result['end_time'] record = Chat_record(content, start_time, end_time, role, result_id) records.append(record) return records def sort_records(self, chat_records): cmpfun = operator.attrgetter('start_time') chat_records.sort(key=cmpfun) return chat_records def sample_from_file(self, file_path): try: samplerate, data = wavfile.read(file_path) except Exception: try: return 0, 0, 0 '''sph = SPHFile(file_path) sph.write_wav(filename=file_path) samplerate, data = wavfile.read(file_path)''' except Exception: traceback.print_exc() os.remove(file_path) return 0, 0, 0 time = data.shape[0] // samplerate return samplerate, data, time def get_content(self, id, company): samplerate, data, time = self.sample_from_file(self.file_path) if samplerate == 0 and data == 0: return 0, 0, 0, 0 # if company == 'jiaoyu' and time < 60: # os.remove( self.file_path ) # return 0, 0, 0, 0 left = [] right = [] if len(data.shape) == 2: for item in data: left.append(item[0]) right.append(item[1]) self.file_path_left = self.file_path[:-4] + '_left.wav' self.file_path_right = self.file_path[:-4] + '_right.wav' wavfile.write(self.file_path_left, samplerate, np.array(left)) wavfile.write(self.file_path_right, samplerate, np.array(right)) left_result = self.asr_audio(self.file_path_left) right_result = self.asr_audio(self.file_path_right) left_result, right_result, sign_change_channel = self.fix_channel(left_result, right_result, 0) os.remove(self.file_path) os.remove(self.file_path_left) os.remove(self.file_path_right) left_record = self.convert_to_record(left_result, 'staff', id) right_record = self.convert_to_record(right_result, 'user', id) right_record.extend(left_record) right_record = self.sort_records(right_record) return right_record, time, 2, 1 else: result = self.asr_audio(self.file_path) record = self.convert_to_record(result, 'staff', id) os.remove(self.file_path) return record, time, 1, 1 def send_back(self, ip, customer_id, sign): sign = '不合格' if sign else '合格' response = requests.get( 'http://39.98.54.147:8005/writeBack?ip={}&customerId={}&checkResult={}'.format(ip, customer_id, sign)) def record_all(self, args): ip = args[0] date = '{}-{}-{}'.format(datetime.datetime.now().year, datetime.datetime.now().month, datetime.datetime.now().day) if not os.path.exists('./{}_data_dir/{}_反馈客户数据.xlsx'.format(ip, date)): fp = open('./{}_data_dir/{}_反馈客户数据.xlsx'.format(ip, date), 'w') if len(args) == 5: fp.write('质检结果\t客服ID\t电话开始时间\t外拨坐席\n') else: fp.write('质检结果\t客服ID\t电话开始时间\t通话时长\t外拨职场\t外拨小组\t外拨坐席\n') else: fp = open('./{}_data_dir/{}_反馈客户数据.xlsx'.format(ip, date), 'a') if len(args) == 5: ip, sign, customer_id, call_date, name = args fp.write('{}\t{}\t{}\t{}\n'.format(sign, customer_id, call_date, name)) else: ip, sign, customer_id, call_date, time, call_place, call_group, name = args fp.write( '{}\t{}\t{}\t{}\t{}\t{}\t{}\n'.format(sign, customer_id, call_date, time, call_place, call_group, name)) fp.close() def optimize_record(self, chat_record, company): last_time = '' stop_sign = False result_sign = False content_list = list() pattern = re.compile(r'(^((?!.).)*对+(,|。)*((?!.).)*$|挂机)') for c in chat_record: if c.content not in [',', '正在呼叫请稍候,']: result = pattern.search(c.content) if result: if c.content.startswith('1'): if stop_sign and c.start < last_time: result_sign = True else: stop_sign = True last_time = c.end_time else: c.content = c.content.replace(',', '') if company == 'jiaoyu': content_list.append([c.content, 0 if c.role == 'staff' else 1]) elif company == 'meituan': # 获取本句的开始时间 minute, second = c.start_time.split(':') minute = int(minute) * 60 second = int(second.split('.')[0]) start_time = minute + second # 获取本句的结束时间 minute, second = c.end_time.split(':') minute = int(minute) * 60 second = int(second.split('.')[0]) end_time = minute + second content_list.append([c.content, 0 if c.role == 'staff' else 1, start_time, end_time]) else: content_list.append([c.content, 1 if c.role == 'staff' else 0]) return content_list, result_sign def task(self, **kwargs): # ip, call_id, customer_id, name, call_date, wav_path): # print( 'key value :{}'.format(kwargs) ) ip = kwargs.get('ip', '') call_id = kwargs.get('call_id', '') # 唯一标示 customer_id = kwargs.get('customer_id', '') company = kwargs.get('company', '') name = kwargs.get('name', '') phone = kwargs.get('phone', '') wav_path = kwargs.get('wav_path', '') call_date = kwargs.get('call_date', '') call_place = kwargs.get('call_place', '') call_group = kwargs.get('call_group', '') call_answer = kwargs.get('call_answer', '') call_transfer = kwargs.get('call_transfer', '') chat_record, time, channel, sign = self.get_content(call_id, company) if not sign: return 0 content_list, stop_sign = self.optimize_record(chat_record, company) if company == 'meituan': sign = meituan_rule.recognition(content_list, call_id, customer_id, name, call_date, wav_path, ip, time, channel, phone, stop_sign) self.record_all([ip, sign, customer_id, call_date, time, call_place, call_group, name]) def post(self): ip = self.get_argument('ip', '') name = self.get_argument('displayName', '') company = self.get_argument('company', '') call_id = self.get_argument('callId', '') customer_id = self.get_argument('customerId', '') phone = self.get_argument('phone', '') wav_path = self.get_argument('wavPath', '') call_date = self.get_argument('callDate', '') call_answer = self.get_argument('answerDate', '') call_transfer = self.get_argument('transferDate', '') call_place = self.get_argument('call_place', '') call_group = self.get_argument('call_group', '') # 提取表单中‘name’为‘file’的文件元数据 file_metas = self.request.files['file'] for meta in file_metas: filename = meta['filename'] self.file_path = '{}/{}_{}.wav'.format(wav_dir, ip, customer_id) # 有些文件需要已二进制的形式存储,实际中可以更改 with open(self.file_path, 'wb') as up: up.write(meta['body']) self.write('finished!') if company == 'meituan': # self.task(company=company, ip=ip, call_id=call_id, customer_id=customer_id, name=name, call_date=call_date, call_place='', call_group='', phone=phone, wav_path=wav_path) p = threading.Thread(target=self.task, kwargs=( {'company': company, 'ip': ip, 'call_id': call_id, 'customer_id': customer_id, 'name': name, 'call_date': call_date, 'call_answer': call_answer, 'call_transfer': call_transfer, 'call_place': call_place, 'call_group': call_group, 'phone': phone, 'wav_path': wav_path})) class transform( RequestHandler ): def get(self): ip = self.get_argument('ip', '') custom_id = self.get_argument('customerId', '') check_result = self.get_argument('checkResult', '') response = requests.get('http://{}:8004/writeBack?customerId={}&checkResult={}'.format(ip, custom_id, check_result), time_out=3) class Get_num( RequestHandler ): def get(self): ip = self.get_argument('ip', '') num = len(glob.glob('./{}_data_dir/*.xlsx'.format(ip))) self.write(str(num)) class Call_back( RequestHandler ): def task(self, ip, company): date = '{}-{}-{}'.format(datetime.datetime.now().year, datetime.datetime.now().month, datetime.datetime.now().day) xlsx_list = glob.glob('./{}_data_dir/*_*_*_*.xlsx'.format(ip)) xlsx_tuple = list() # 按时长排序 for xlsx_file in xlsx_list: try: xlsx_tuple.append( (xlsx_file, int(xlsx_file.split('_')[-1].split('.')[0])) ) except Exception: pass xlsx_tuple = sorted(xlsx_tuple, key=lambda x:x[-1], reverse=True) wb = Workbook() ws = wb.active num_1 = 0 num_2 = 0 ws['A1'] = '话单ID' ws['B1'] = '客户ID' ws['C1'] = '姓名/修正意见' ws['D1'] = '末次接通时间/错误类型' ws['E1'] = '音频地址/错误规则' ws['F1'] = '命中语句/电话号码' ws['G1'] = '录音内容' for xlsx, time in xlsx_tuple: if xlsx.split('_')[-2] == '1': num_1 += 1 else: num_2 += 1 wb_s = load_workbook(xlsx) ws_s = wb_s[wb_s.sheetnames[0]] for row in ws_s.values: # row = row[:list(row).index(None)] ws.append(row) ws.append(['', ]) wb.save('./{}_data_dir/{}_{}_{}_{}_总结.xlsx'.format(ip, date, ip, num_1, num_2)) def get(self): ip = self.get_argument('ip', '') company = self.get_argument('company', '') p = threading.Thread(target=self.task, args=(ip, company)) p.start() self.write('success') class Start_jiao( RequestHandler ): def get(self): date = self.get_argument('date', '') company_id = self.get_argument('companyId', '') # jiaoyu.quality_test_jiaoyu(date, company_id) p = threading.Thread(target=jiaoyu.quality_test_jiaoyu, args=(date, company_id, 'jiaoyu')) p.start() self.write('success') class Start_jingka( RequestHandler ): def get(self): date = self.get_argument('date', '') company_id = self.get_argument('companyId', '') # jiaoyu.quality_test_jiaoyu(date, company_id) p = threading.Thread(target=jiaoyu.quality_test_jiaoyu, args=(date, company_id, 'jingka')) p.start() self.write('success') class Start_caishang( RequestHandler ): def get(self): date = self.get_argument('date', '') company_id = self.get_argument('companyId', '') # jiaoyu.quality_test_jiaoyu(date, company_id) p = threading.Thread(target=jiaoyu.quality_test_jiaoyu, args=(date, company_id, 'caishang')) p.start() self.write('success') class Start_fandeng( RequestHandler ): def get(self): date = self.get_argument('date', '') company_id = self.get_argument('companyId', '') # jiaoyu.quality_test_jiaoyu(date, company_id) p = threading.Thread(target=jiaoyu.quality_test_jiaoyu, args=(date, company_id, 'fandeng')) p.start() self.write('success') def send_wechat_warning(customer_id, ip, text): headers = {'Content-Type': 'application/json'} title = '京东金条(质检)' text = {'content': '{}\n{}\n{}\n{}'.format(title, ip, customer_id, text) } webhook = 'https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=b517f035-d07a-4131-8f91-20fba7b504ca' data = { 'msgtype': 'text', 'text': text } data = json.dumps(data) response = requests.request('POST', webhook, headers=headers, data=data, timeout=1) content = response.text if __name__ == '__main__': tornado.options.parse_command_line() app = tornado.web.Application([ (r'/quality_test', Quality_test), (r'/meituan_quality_test', Meituan_Quality_test), (r'/call_back', Call_back), (r'/get_num', Get_num), (r'/start_jiaoyu', Start_jiao), (r'/start_jingka', Start_jingka), (r'/start_fandeng', Start_fandeng), (r'/start_caishang', Start_caishang), ], static_path=os.path.join(os.path.dirname(__file__), "static"), template_path=os.path.join(os.path.dirname(__file__), "template"), debug=False ) http_server = tornado.httpserver.HTTPServer(app) http_server.listen(port) http_server.start(20) print("starting") tornado.ioloop.IOLoop.current().start() print("starting ... ")