前言

上一期我写了接口通过python使用api抓取udesk客服系统数据并同步到本地mysql数据库,为自动化做了一些基础工作。

近期我又被分配了新的工作内容:不断更新客服系统机器人的知识库内容。

因为做技术支持的工程师有好几个(我也是其中之一),而对接客户的客服只有我一个,我们平时总结的一些常用问题都需要我手动去录入,比较麻烦。

我的思路是使用一个共享表格,大家想到什么问答就填到表格里面,然后再使用一个自动化程序录入到机器人知识库里面。

正好wps云文档提供了编程功能和网络接口,所以第一时间想到通过wps+网络服务使用api更新udesk知识库问题。

这里的网络服务选择使用django,正好练练手。

django配置

因为django刚学,还不是很熟练,这里就简单写了一个views调用之前写的udesk的机器人接口。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# in addfaq/views.py
import sys
import json
import pandas as pd
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from rest_framework import serializers
from KMRobot import KMRobot


def decode_unicode(obj):
'''
把字典中的 unicode 字符解码成正常字符
'''
if isinstance(obj, str):
return eval(repr(obj))
elif isinstance(obj, list):
return [decode_unicode(item) for item in obj]
elif isinstance(obj, dict):
return {decode_unicode(k): decode_unicode(v) for k, v in obj.items()}
return obj


class MySerializer(serializers.Serializer):
'''数据验证'''
token = serializers.CharField(max_length=100)
data = serializers.JSONField()

def validate_name(self, value):
if value != 'token':
raise serializers.ValidationError("token is invalid!")
return value

def validate_data(self, value):
value = decode_unicode(value)
try:
df = pd.DataFrame(value)
except Exception:
raise serializers.ValidationError("Data must be a JSON object")
cols = ["id", "category", "content",
"answer", "keyword", "suggestsList"]
if list(df.columns) != cols:
raise serializers.ValidationError(
f"columns must be: {' '.join(cols)}")
return df


def addfaq(df: pd.DataFrame):
'''添加知识库问题,如果已有id则不添加'''
t = KMRobot()
t.faqlist2mysql()
df = df[(df['category'] != "") & (
df['content'] != "") & (df['answer'] != "")]
for v in range(2, len(df)):
if df.iloc[v, 0] == "":
keyword = None if df.iloc[v, 4] == "" else df.iloc[v, 4]
suggestsList = None if df.iloc[v, 5] == "" else df.iloc[v, 5]
category = df.iloc[v, 1]
content = df.iloc[v, 2]
answer = df.iloc[v, 3]
id = t.addfaq(category=category, content=content, answer=answer,
keyword=keyword, suggestsList=suggestsList)
df.iloc[v, 0] = id
t.faqlist2mysql()
return df


class MyAPIView(APIView):
def post(self, request):
serializer = MySerializer(data=request.data)
if serializer.is_valid():
# 处理验证后的数据
data = serializer.validated_data["data"]
data = addfaq(data)
return Response({'status': 'success', 'data': data})
return Response({'status': 'error', 'errors': serializer.errors},
status=status.HTTP_400_BAD_REQUEST)

wps 配置

在 效率-高级开发-AirScript脚本编辑器 中可以编写 JavaScript 脚本,并且支持定时任务。

这个脚本将云文档的数据以json方式发送给网络服务,网络服务会返回更新后的数据(主要是更新了问题的id),写回云文档。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
//将json数据写回数据表中
function write_json(obj, sheet) {
const keys = Object.keys(obj);
const ncol = keys.length;
var nrow;

for (let i = 0; i < ncol; i++) {
nrow = obj[keys[i]].length
sheet.Cells(1, i + 1).Value2 = keys[i]
for (let j = 0; j < nrow; j++) {
sheet.Cells(j + 2, i + 1).Value2 = obj[keys[i]][j]
}
}
}

const sheet = ActiveSheet
const usedRange = sheet.UsedRange
const data = []

//读取云文档数据
for (let row = usedRange.Row + 1; row <= usedRange.Row + usedRange.Rows.Count - 1; row++) {
const rowData = {}
for (let col = usedRange.Column; col <= usedRange.Column + usedRange.Columns.Count - 1; col++) {
const cell = sheet.Cells(row, col)
const header = sheet.Cells(usedRange.Row, col).Text
rowData[header] = cell.Text
}
data.push(rowData)
}
body = {
"token": "token",
"data": data
}
jsonData = JSON.stringify(body)
const resp = HTTP.post('https://example.com/udeskapi/addfaq/', jsonData)
const content = resp.json()
const data2 = content.data
if (content.status == "success") {
usedRange.ClearContents()
write_json(data2, sheet)
} else {
console.log(content)
}