123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456 |
- # -*- codeing = utf-8 -*-
- # @Time : 2022/8/29 14:43
- # @Author : Clown
- # @File : EC_招商CRM.py
- # @Software : PyCharm
- import requests
- import hashlib
- import time
- import csv
- import json
- import pandas as pd
- import math
- from datetime import timedelta, datetime
- from dateutil.parser import parse
- # corpid : 17409173
- # get_sign : 签名算法
- def get_sign(app_id, app_secret, timestamp):
- '''
- :param app_id: 应用ip 914890189023739904
- :param app_secret: 应用密钥 Ur2K41t71RrxYn7eWhN
- :param timestamp: 时间戳 毫秒
- :return: 加密密文
- '''
- str = 'appId=' + app_id + '&appSecret=' + app_secret + '&timeStamp=' + timestamp
- hl = hashlib.md5()
- hl.update(str.encode(encoding='utf-8'))
- return hl.hexdigest().upper()
- def getCustomDet(corpid,sign,timestamp,pageNo):
- url = 'https://open.workec.com/v2/customer/queryList'
- headers = {'Content-Type':'application/json',
- 'X-Ec-Cid':corpid,
- 'X-Ec-Sign':sign,
- 'X-Ec-TimeStamp':timestamp}
- # 全局浏览
- # json = {
- # "__grouble_id": "x"
- # }
- # 排序浏览 asc升序,desc降序
- json = {
- "pageNo": pageNo,
- "pageSize": 50,
- 'orderBy':[{"sortField":'createTime',
- "sortType":'desc'}]
- }
- resp = requests.post(url,headers=headers,json=json).json()
- # print(resp)
- return resp
- def selectCustomInfo(corpid,sign,timestamp,selectInfoFile,df_out_path):
- df = pd.read_excel(selectInfoFile,dtype=str)
- infoList = df['号码']
- print(len(infoList))
- df_out = []
- infoList50 = []
- for n in range(round(len(infoList)/50+1)):
- x = 50 * n
- y = 50 * (n + 1)
- info = ','.join(infoList[x:y])
- url = 'https://open.workec.com/v2/customer/queryExist'
- headers = {'Content-Type': 'application/json',
- 'X-Ec-Cid': corpid,
- 'X-Ec-Sign': sign,
- 'X-Ec-TimeStamp': timestamp}
- json_params = {"mobile":str(info)}
- resps = requests.post(url,headers=headers,json=json_params).json()['data']
- for resp in resps:
- df_out_dict = {}
- num = resp['num']
- df_out_dict['mobile'] = resp['mobile']
- df_out_dict['queryExistNum'] = num
- print(info,num)
- df_out.append(df_out_dict)
- n += 1
- df_out = pd.DataFrame(df_out)
- df_out.to_excel(df_out_path)
- def getOkCustom(corpid,sign,timestamp,pageNo):
- url = 'https://open.workec.com/v2/customer/queryList'
- headers = {'Content-Type': 'application/json',
- 'X-Ec-Cid': corpid,
- 'X-Ec-Sign': sign,
- 'X-Ec-TimeStamp': timestamp}
- # 全局浏览
- # json = {
- # "__grouble_id": "x"
- # }
- # 排序浏览 asc升序,desc降序
- json = {
- "labelIds":[83625192],
- "pageNo": pageNo,
- "pageSize": 50,
- 'orderBy': [{"sortField": 'createTime',
- "sortType": 'desc'}]
- }
- resp = requests.post (url, headers=headers, json=json).json()
- # print(resp)
- return resp
- def getInfo(users_dict,corpid,sign,timestamp,pagesNo,out_file):
- f = open(out_file,mode='w',encoding="utf-8-sig",newline='')
- csv_writer = csv.writer(f)
- title = ['创建日期','资源id','资源来源','最后跟进人','组别','最后跟进时间','备注']
- csv_writer.writerow(title)
- for pageNo in range(pagesNo):
- info_data = getCustomDet(corpid,sign,timestamp,pageNo+1)
- for info in info_data['data']['list']:
- createTime = info['createTime']
- crmId = info['crmId']
- channel = info['channel']
- lastFollowUserId = 'userID:' +str(info['lastFollowUserId'])
- try:
- lastFollowUser = users_dict[lastFollowUserId]['userName']
- deptName = users_dict[lastFollowUserId]['deptName']
- except:
- lastFollowUser = lastFollowUserId
- deptName = '未知'
- try:
- lastContactTime = info['lastContactTime']['time']
- except:
- lastContactTime = ''
- try:
- memo = info['memo']
- except:
- memo = ''
- row = [createTime,crmId,channel,lastFollowUser,deptName,lastContactTime,memo]
- csv_writer.writerow(row)
- print('page:'+ str(pageNo) + 'ok')
- def getOkInfo(users_dict,corpid,sign,timestamp,pagesNo,out_file):
- f = open(out_file,mode='w',encoding="utf-8-sig",newline='')
- csv_writer = csv.writer(f)
- title = ['创建日期','资源id','资源来源','最后跟进人','组别','最后跟进时间','备注']
- csv_writer.writerow(title)
- for pageNo in range(pagesNo):
- info_data = getOkCustom(corpid,sign,timestamp,pageNo+1)
- for info in info_data['data']['list']:
- createTime = info['createTime']
- crmId = info['crmId']
- channel = info['channel']
- lastFollowUserId = 'userID:' +str(info['lastFollowUserId'])
- try:
- lastFollowUser = users_dict[lastFollowUserId]['userName']
- deptName = users_dict[lastFollowUserId]['deptName']
- except:
- lastFollowUser = lastFollowUserId
- deptName = '未知'
- try:
- lastContactTime = info['lastContactTime']['time']
- except:
- lastContactTime = ''
- try:
- memo = info['memo']
- except:
- memo = ''
- row = [createTime,crmId,channel,lastFollowUser,deptName,lastContactTime,memo]
- csv_writer.writerow(row)
- print('page:'+ str(pageNo) + 'ok')
- def getUserInfo(corpid,sign,timestamp):
- #获取组织架构信息,主要是对应上id和人名
- url = 'https://open.workec.com/v2/org/struct/info'
- params = 'needUser=true'
- headers = {'Content-Type': 'application/json',
- 'X-Ec-Cid': corpid,
- 'X-Ec-Sign': sign,
- 'X-Ec-TimeStamp': timestamp}
- resp = requests.get(url,params=params,headers=headers).json()
- return resp
- # def runT():
- # pages = OrdersInfoByPages()
- # executor = ThreadPoolExecutor (pages)
- # for i in range(pages):
- # offset = i*100
- # executor.submit (lookupPagesInfo, offset)
- # executor.shutdown(wait=True)
- def getLabel(corpid,sign,timestamp):
- url = 'https://open.workec.com/v2/label/getLabelInfo'
- json_params = {'groupValue':''}
- headers = {'Content-Type': 'application/json',
- 'X-Ec-Cid': corpid,
- 'X-Ec-Sign': sign,
- 'X-Ec-TimeStamp': timestamp}
- resp = requests.post(url, json=json_params, headers=headers).text
- print(resp)
- def addCustomers(corpid,sign,timestamp,customerList):
- #新增客户
- #来源渠道备注:47625为400电话,
- #customerList = [{}]
- url = 'https://open.workec.com/v2/customer/addCustomer'
- headers = {'Content-Type': 'application/json',
- 'X-Ec-Cid': corpid,
- 'X-Ec-Sign': sign,
- 'X-Ec-TimeStamp': timestamp}
- json_params = {'optUserId':17409174,
- 'list':customerList,
- 'notify':False,
- 'repeat':False,
- 'supply_detail':False}
- resp = requests.post(url,headers=headers,json=json_params).json()
- failureList = resp['data']['failureList']
- successIdList = resp['data']['successIdList']
- if len(successIdList) == 1:
- print('ok')
- elif len(failureList) == 1:
- print('error')
- def getChannelSource(corpid,sign,timestamp):
- #查询来源信息
- url= 'https://open.workec.com/v2/customer/getChannelSource'
- headers = {'Content-Type': 'application/json',
- 'X-Ec-Cid': corpid,
- 'X-Ec-Sign': sign,
- 'X-Ec-TimeStamp': timestamp}
- resp = requests.get(url,headers=headers).json()
- print(json.dumps(resp,ensure_ascii=False))
- def findUserInfoById(corpid,sign,timestamp,userId):
- url = 'https://open.workec.com/v2/org/user/findUserInfoById'
- headers = {'Content-Type': 'application/json',
- 'X-Ec-Cid': corpid,
- 'X-Ec-Sign': sign,
- 'X-Ec-TimeStamp': timestamp}
- json_params = {'userId':str(userId),'deptInfo':False}
- resp = requests.post(url,headers=headers,json=json_params).json()
- # print(resp)
- return resp
- def getCustomersTrajectory(corpid,sign,timestamp,trajectoryRequestDict):
- state_dict = {"1001": "发送短信", "1002": "拨打对方电话", "1003": "网站客服会话", "1004": "EC会话", "1005": "QQ会话", "1006": "发送邮件",
- "1007": "接听对方电话", "1008": "接收邮件", "1009": "电话会议", "1010": "拨打云总机电话", "1011": "接听云总机电话",
- "2003": "日历提醒", "2001": "定时提醒", "2002": "提醒销售计划", "3001": "新增客户", "3002": "新增客户资料", "3003": "更新客户资料",
- "3004": "更新客户标签", "3005": "关联EC", "3006": "取消EC关联", "3007": "关联QQ", "3008": "取消QQ关联", "3009": "转让客户",
- "3010": "合并客户", "3011": "分配客户", "3012": "领取客户", "3013": "放弃客户", "3014": "添加销售计划", "3015": "修改销售计划",
- "3016": "使用销售模板", "3017": "更新客户阶段", "3018": "关联公司", "3019": "取消公司关联", "3020": "上传头像",
- "3021": "新增共享同事", "3022": "取消共享同事", "3023": "退出共享关系", "3024": "转为公司导入", "4000": "添加跟进记录",
- "6000": "微信活动", "7000": "拜访客户"}
- crmIds = trajectoryRequestDict['crmIds']
- lastContactTime = trajectoryRequestDict['lastContactTime']
- memo = trajectoryRequestDict['memo'] #memo决定是否为首次获取日志
- #查询用户信息
- url_crmInfo = 'https://open.workec.com/v2/customer/queryList'
- json_params_crmInfo = {'crmIds': [crmIds]}
- url = 'https://open.workec.com/v2/customer/getTrajectory'
- headers = {'Content-Type': 'application/json',
- 'X-Ec-Cid': corpid,
- 'X-Ec-Sign': sign,
- 'X-Ec-TimeStamp': timestamp}
- resp_crmInfo = requests.post (url_crmInfo, headers=headers, json=json_params_crmInfo).json ()['data']
- # print(resp_crmInfo)
- #获取当前跟进人
- try:
- followerName = findUserInfoById (corpid, sign, timestamp, resp_crmInfo['list'][0]['lastFollowUserId'])['data']['name']
- except:
- followerName = '离职员工'
- #获取创建时间及最近一次跟进时间
- try:
- createTime = resp_crmInfo['list'][0]['createTime']
- lastTime = resp_crmInfo['list'][0]['contactTime']
- except:
- createTime = resp_crmInfo['list'][0]['createTime']
- lastTime = createTime
- # print(createTime,lastTime)
- #依据是否首次获取跟进日志,构建日志查询参数
- endTime = parse (str (parse (str (lastTime)) + timedelta (seconds=2))).strftime ('%Y-%m-%d %H:%M:%S')
- #首次
- if int(memo) == 0:
- startTime = parse (str (parse (str (createTime)) + timedelta (seconds=-2))).strftime ('%Y-%m-%d %H:%M:%S')
- # 判断日期间隔
- n = math.ceil ((parse (str (endTime)).timestamp () - parse (str (startTime)).timestamp ()) / 3600 / 24 / 30)
- if n <= 1:
- json_params = [{'crmIds':str(crmIds),
- 'date':{'startTime':startTime,
- 'endTime':endTime}}]
- #日期间隔大于30天
- else:
- json_params = []
- x = 1
- for i in range (n):
- if x < n:
- m = parse (str (parse (str (startTime)) + timedelta (days=30))).strftime ('%Y-%m-%d %H:%M:%S')
- x += 1
- else:
- m = endTime
- json_param = {'crmIds':str(crmIds),
- 'date':{'startTime':startTime,
- 'endTime':m}}
- json_params.append(json_param)
- startTime = parse (str (parse (str (m)) + timedelta (seconds=1))).strftime ('%Y-%m-%d %H:%M:%S')
- # 二次
- elif int(memo) == 1:
- startTime = parse (str (parse (str (lastContactTime.replace('T',' '))) + timedelta (seconds=1))).strftime ('%Y-%m-%d %H:%M:%S')
- json_params = [{'crmIds': str (crmIds),
- 'date': {'startTime': startTime,
- 'endTime': endTime}}]
- log = ''
- for json_param in json_params:
- resp = requests.post(url,headers=headers,json=json_param).json()['data']
- trajectoryList = resp['trajectoryList']
- #当前时间内是否有更新
- if len(trajectoryList) == 0:
- trajectoryResult = {'trajectoryLog': log,
- 'result':-2,
- 'followerName': followerName,
- 'lastContactTime': lastTime.replace (' ', 'T')}
- else:
- for trajectory in trajectoryList:
- createTime = trajectory['createTime']
- trajectoryType = trajectory['trajectoryType']
- trajectoryName = state_dict[str(trajectoryType)]
- userId = trajectory['userId']
- try:
- userName = findUserInfoById (corpid, sign, timestamp, userId)['data']['name']
- if userName == '谢总':
- userName = '系统分配'
- else:
- ...
- except:
- userName = '员工已离职'
- if trajectoryType == 4000:
- recordInfo = f"\n备注:【{trajectory['content']}】"
- elif trajectoryType in [3009]:
- receiveUserIds = trajectory['receiveUserIds']
- try:
- receiveUserName = findUserInfoById (corpid, sign, timestamp, receiveUserIds)['data']['name']
- except:
- receiveUserName = '离职员工'
- recordInfo = f'\n备注:客户转让至【{receiveUserName}】'
- else:
- recordInfo = ''
- text_out = f'{createTime}--跟进动作:{trajectoryName}--操作人:{userName}{recordInfo}'
- # print(text_out)
- log = log + text_out + '\n'
- # print(trajectoryType)
- if trajectoryType == 3013:
- mark = -1
- elif trajectoryType in [3001,3011,3012,3009]:
- mark = 0
- else:
- mark = 1
- trajectoryResult = {'trajectoryLog':log,
- 'result':mark,
- 'followerName':followerName,
- 'lastContactTime':lastTime.replace(' ','T')}
- # print(trajectoryResult)
- return trajectoryResult
- def runTrajectory(trajectoryRequestDict):
- '''
- result 为int 数值为0,1,-1 【0表示未跟进,1表示跟进中,-1表示客户被放弃】
- '''
- corpid = '17409173'
- timestamp = str (int (round (time.time () * 1000)))
- app_id = '914890189023739904'
- app_secret = 'Ur2K41t71RrxYn7eWhN'
- sign = get_sign (app_id, app_secret, str (timestamp))
- try:
- trajectoryResult = getCustomersTrajectory(corpid,sign,timestamp,trajectoryRequestDict)
- except Exception as e:
- print(e)
- print ('input Info Error1!')
- trajectoryResult= {'trajectoryLog': '参数有误', 'followerName': '', 'result': 'error', 'lastContactTime':'Null'}
- return trajectoryResult
- # 批量查询客户信息
- def selectCustomsInfo(clue_photo_num_list,cycle_hours):
- # 入参格式 clue_photo_num_list = ['13775234802,19232722757,19903546661,18164685587,18655626682,13152011389,18709596396,15536158166,13752862728,17767157888,13812552265,18751168688,13868980059,15994211909,15330337158,18069510127,16685833888,13989666719,18082610680,13629286297,15151093376,15349370007,18696933445,13777447476,19218748440,13765636503,18655626682,15703592119,15703592119,15996391796,16613882968,18968498788,18261563639,18012565368,18012565368,13867934378,13813841224,18969513827,13765636503,18984319715,18963978060,15514586363,13813000590,13894722167,13100716617,13100716617,15202388770,18716736100,13801584013']
- corpid = '17409173'
- timestamp = str(int(round(time.time() * 1000)))
- app_id = '914890189023739904'
- app_secret = 'Ur2K41t71RrxYn7eWhN'
- sign = get_sign(app_id, app_secret, str(timestamp))
- url = 'https://open.workec.com/v2/customer/queryList'
- headers = {'Content-Type': 'application/json',
- 'X-Ec-Cid': corpid,
- 'X-Ec-Sign': sign,
- 'X-Ec-TimeStamp': timestamp}
- out_list = []
- for group in clue_photo_num_list:
- params = {'mobile':group}
- resp = requests.post(url,headers=headers,json=params).text
- resp = json.loads(resp)
- for i in resp['data']['list']:
- createTime = i['createTime']
- noteTime = (parse(createTime)+timedelta(hours = cycle_hours)).strftime('%Y-%m-%d %H:%M:%S')
- crmId = i['crmId']
- mobile = i['mobile'][-11:]
- print(mobile,crmId,createTime,cycle_hours,noteTime,'')
- out_list.append((mobile,crmId,createTime,cycle_hours,noteTime,None,'同步crmId'))
- print(out_list)
- return out_list
- if __name__ == '__main__':
- if 1==0:
- corpid = '17409173'
- timestamp = str(int(round(time.time() * 1000)))
- app_id = '914890189023739904'
- app_secret = 'Ur2K41t71RrxYn7eWhN'
- sign = get_sign(app_id, app_secret, str(timestamp))
- # getLabel (corpid, sign, str(timestamp))
- crmIds = [6649346389,6716036532,6713477481]
- trajectoryRequestDict = {'crmIds':8428482275,'memo':0,'lastContactTime':0}
- getCustomersTrajectory (corpid, sign, timestamp, trajectoryRequestDict)
- clue_photo_num_list = ['16685833888,13765636503,18751168688,15994211909,18969513827,15330337158,13100716617,18716736100,13801584013,15900818382,18696933445,18752808628,15202388770,18069510127,18164685587,18957915191,15180810078,15161112338,18963978060,16613882968,18082610680,13752862728,13812552265,13011848788,13629286297,15349370007,13914701944,13867934378,18611013399,13777126490,13349994865,15996391796,18984319715,18968498788,18012565368,15050580681,15605853405,18131725305,15703592119,18709596396,15514586363,13851034333,13777447476,13813000590,18280502701,19154961250,13152011389,15536158166,18609680601,18655626682', '19903546661,13894722167,13989666719,13813841224,13775234802,15507281555,19218748440,15151093376,17767157888,19232722757,18762280927,18261563639,13868980059']
- cycle_hours = 15
- selectCustomsInfo(clue_photo_num_list,cycle_hours)
- if 1 == 0:
- user_data = getUserInfo (corpid, sign, str(timestamp))
- # print(json.dumps(user_data,ensure_ascii=False))
- users_dict = {}
- for user in user_data['data']['users']:
- deptId = user['deptId']
- if deptId == 17440441:
- users_dict['userID:' + str (user['userId'])] = {"userName": user['userName'], "deptName": '招商一部'}
- elif deptId == 17440442:
- users_dict['userID:' + str (user['userId'])] = {"userName": user['userName'], "deptName": '招商二部'}
- elif deptId == 18659257:
- users_dict['userID:' + str (user['userId'])] = {"userName": user['userName'], "deptName": '招商三部'}
- else:
- ...
- # print(json.dumps(users_dict,ensure_ascii=False))
- if 1 == 0:
- # print(sign)
- out_file = f'C:/Users/ClownHe/Desktop/导出/{timestamp}招商数据.csv'
- total_data = getCustomDet(corpid,sign,str(timestamp),1)
- pagesNo = total_data['data']['page']['maxPageNo']
- getInfo (users_dict, corpid, sign, str(timestamp), pagesNo, out_file)
- if 1 == 0:
- out_file = f'C:/Users/ClownHe/Desktop/导出/{timestamp}招商签约数据.csv'
- total_data = getOkCustom (corpid, sign, str (timestamp), 1)
- pagesNo = total_data['data']['page']['maxPageNo']
- getOkInfo (users_dict, corpid, sign, str (timestamp), pagesNo, out_file)
- getChannelSource (corpid, sign, timestamp)
- selectInfoFile = 'C:/Users/ClownHe/Desktop/goods/浆小白线索数据.xlsx'
- df_out_path = 'C:/Users/ClownHe/Desktop/goods/浆小白线索数据(核对).xlsx'
- selectCustomInfo (corpid, sign, str (timestamp), selectInfoFile, df_out_path)
- # list_a = [{
- # "followUserId":17409174,
- # "mobile":"18795412345",
- # "name":"测试数据请忽略",
- # 'memo':'400热线'
- # }]
- # addCustomers (corpid, sign, timestamp, list_a)
|