ZZGL:开发指定关键词的分词系统减少在线问答问题的重复率

2014-01-14 1,886 1 开发! 大超超。

140114弹窗提示是否继续提交.png

图为提取出关键词“勤工助学”“工资”进行数据库搜索的结果


鼓足一口气开发了在线留言的预检测系统,为了减少问题重复率、提高资助工作效率。欢迎体验:在线问答 - 武汉大学学生资助管理网

开发原理:根据指定资助工作中的在线问答大家经常问的问题所包含的关键词,在此有限关键词内对用户输入的问答内容进行匹配,如果匹配到关键词,则将搜索此关键词的结果返回给用户,这些结果中可能包含了其他用户问过的类似问题,就可以一下子解答掉用户的疑惑而不需要等待回复。

存在缺点:关键词匹配效果不一定好,需要后期不断优化关键词列表、提高命中率。

前端截图:如上图。

前端代码AJAX查询数据库的代码就不发了)

// 在用户点击提交、触发检查表单事件时执行检测关键词等
function checkForm(myform){
    var tag = 0;
    var ct = document.getElementById("MsgContent").value;
    var radioObj = document.getElementsByName("MsgClassId");
    for(var i=0;i<radioObj.length;i++){
        if(radioObj[i].checked){
            tag=1;
        }
    }
    if(tag==0)  {
        alert("请选择问题类别!以便相关人员及时给你回复");
        return false;
    }
    if(ChkMail(document.getElementById("Email"))==false){
         alert("请输入正确的邮箱地址!");  
         document.getElementById("Email").focus(); 
         return false;
    }
    if( ct=='' ){
        alert("请输入内容!");  
        document.getElementById("MsgContent").focus(); 
        return false;
    }
    if( document.getElementById("vCode").value=='' ){
        alert("请输入验证码!");  
        document.getElementById("vCode").focus(); 
        return false;
    }
         
    // 在用户提交时检测是否已有类似问题
    // 生成智能匹配关键词 @ 2014-01-14 12:08:36 & DCC
    var kw_arr = '<%
    set fs=server.createobject("scripting.filesystemobject")
    file=server.mappath("../Admin/IOA/dvKwlist.db.txt")
    set txt=fs.opentextfile(file,1,true)
    for n=1 to 520
        if txt.atendofstream then exit for
        line=txt.readline
        response.write "," & line
    next
    %>'.substr(1).split(',').sort(function(a,b){
            if (a.length>b.length) return -1;
            else if(a.length==b.length) return 0;
            else return 1;
        });
         
    // 对内容进行遍历,提取可能的关键词
    var res_tmp = new Array();
    $.each(kw_arr, function(k, v){
        if( ct.indexOf(v)!==-1 ) res_tmp.push(v);
    });
    // 如果确实匹配到了,那么进行关键字查询数据库
    // 只出现一次弹出层
    cfg_.modal_shown = 0;
    if( res_tmp.length>0 && cfg_.modal_shown==0){
        // 防止多个关键词重复匹配同一条留言
        msgid_arr = new Array();
             
        $.each(res_tmp, function(k, v){
            $.get(cfg_.AJAX_URL, {t:'message_getSimilar', kw:escape(v)}, function(d){
                d = d.substr(7).split('|@dcc#|');
                var d_html = '';
                $.each(d, function(kk, vv){
                    var dd = vv.split('@jdcc#');
                    // 如果之前已经匹配到此条内容,则跳过
                    if( $.inArray(dd[5], msgid_arr)!==-1 ) return;
                    msgid_arr.push(dd[5]);
                    d_html = '<div class="ajax-msglist"><div class="Wen"><div>'+dd[0]+'</div><span class="subColor">提问时间:'+dd[1]+' 所在类别:'+dd[2]+'</span></div><div class="Da _bo-rad"><div>'+dd[3]+'</div><span class="subColor">回复时间:'+dd[4]+'</span></div></div>';
                    d_html = d_html.replace(v, '<font style="color:#f00;" title="关键词匹配">'+v+'</font>');
                    $('.md-body').append(d_html);
                });
                cfg_.modal_shown = 1;
                $('.modal').removeClass('_hide');
                $('.modal-backdrop').removeClass('_hide');
                     
                // 绑定取消按键
                $('.mdf-cancel').unbind('click').click(function(){
                    $('.modal').addClass('_hide');
                    $('.modal-backdrop').addClass('_hide');
                });
                     
                // 绑定仍然提交按钮
                $('.mdf-save').unbind('click').click(function(){
                    $('.modal').addClass('_hide');
                    $('.modal-backdrop').addClass('_hide');
                    myform.submit();
                });
                     
            });
        });
             
        return false;
    }
         
    return true;
}

弹出层HTML代码:

<div class="modal _hide"><div class="md-head">根据提取关键词为您搜索出了若干结果:</div><div class="md-body"></div><div class="md-foot"><span class="mdf-info">为提高效率、减少重复问题,如果您已找到想要的答案,建议选择“不提交了”。</span><button class="mdf-cancel btn-success btn">不提交了</button> <button class="mdf-save btn-danger btn">仍然提交</button></div></div>
<div class="modal-backdrop _hide"></div>

弹出层CSS代码:

.modal{position:fixed;top:20%;left:30%;right:30%;z-index:1050;width:auto;margin:0;background-color:#ffffff;border:1px solid #999;border:1px solid rgba(0, 0, 0, 0.3);*border:1px solid #999;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 3px 7px rgba(0, 0, 0, 0.3);-moz-box-shadow:0 3px 7px rgba(0, 0, 0, 0.3);box-shadow:0 3px 7px rgba(0, 0, 0, 0.3);-webkit-background-clip:padding-box;-moz-background-clip:padding-box;background-clip:padding-box;outline:none;}
.modal-backdrop, .modal-backdrop.fade.in {
opacity: 0.6;
filter: alpha(opacity=60);
}
.modal-backdrop {
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    z-index: 1040;
    background-color: #000000;
    background-image: url(img/overlay.png);
}
.md-head{
    padding: 10px;
    font-size: 18px;
    font-weight: 700;
    border-bottom: 1px solid #ccc;
         
}
.md-body{
    padding: 10px;
    max-height:430px;
    overflow-y:scroll;
}
.md-foot{
    position:relative;
    padding: 14px 15px 15px;
    margin-bottom: 0;
    text-align: right;
    background-color: #f5f5f5;
    border-top: 1px solid #ddd;
    -webkit-border-radius: 0 0 6px 6px;
    -moz-border-radius: 0 0 6px 6px;
    border-radius: 0 0 6px 6px;
    -webkit-box-shadow: inset 0 1px 0 #ffffff;
    -moz-box-shadow: inset 0 1px 0 #ffffff;
    box-shadow: inset 0 1px 0 #ffffff;
}
.mdf-info{position:absolute;left:10px;color:#999;font-size:12px;top:28px;}

弹出层中的按钮CSS代码(从bootstrap中提取的):

.btn{
    display: inline-block;
    padding: 4px 12px;
    margin-bottom: 0;
    font-size: 14px;
    line-height: 20px;
    text-align: center;
    vertical-align: middle;
    cursor: pointer;
    color: #333333;
    text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75);
    background-color: #f5f5f5;
    background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6);
    background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6));
    background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6);
    background-image: -o-linear-gradient(top, #ffffff, #e6e6e6);
    background-image: linear-gradient(to bottom, #ffffff, #e6e6e6);
    background-repeat: repeat-x;
    filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0);
    border-color: #e6e6e6 #e6e6e6 #bfbfbf;
    border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
    filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
    border: 1px solid #cccccc;
    border-bottom-color: #b3b3b3;
    -webkit-border-radius: 4px;
    -moz-border-radius: 4px;
    border-radius: 4px;
    -webkit-box-shadow: inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05);
    -moz-box-shadow: inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05);
    box-shadow: inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05);
}
     
.btn-block {
    display: block;
    width: 100%;
    padding-left: 0;
    padding-right: 0;
    -webkit-box-sizing: border-box;
    -moz-box-sizing: border-box;
    box-sizing: border-box;
}
     
.btn-primary{
    color: #ffffff;
    text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
    background-color: #006dcc;
    background-image: -moz-linear-gradient(top, #0088cc, #0044cc);
    background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));
    background-image: -webkit-linear-gradient(top, #0088cc, #0044cc);
    background-image: -o-linear-gradient(top, #0088cc, #0044cc);
    background-image: linear-gradient(to bottom, #0088cc, #0044cc);
    background-repeat: repeat-x;
    filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0044cc', GradientType=0);
    border-color: #0044cc #0044cc #002a80;
    border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
    filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
}
     
.btn-success {
    color: #ffffff;
    text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
    background-color: #5bb75b;
    background-image: -moz-linear-gradient(top, #62c462, #51a351);
    background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#51a351));
    background-image: -webkit-linear-gradient(top, #62c462, #51a351);
    background-image: -o-linear-gradient(top, #62c462, #51a351);
    background-image: linear-gradient(to bottom, #62c462, #51a351);
    background-repeat: repeat-x;
    filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff51a351', GradientType=0);
    border-color: #51a351 #51a351 #387038;
    border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
    filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
}
     
.btn-danger{
    color: #ffffff;
    text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
    background-color: #da4f49;
    background-image: -moz-linear-gradient(top, #ee5f5b, #bd362f);
    background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#bd362f));
    background-image: -webkit-linear-gradient(top, #ee5f5b, #bd362f);
    background-image: -o-linear-gradient(top, #ee5f5b, #bd362f);
    background-image: linear-gradient(to bottom, #ee5f5b, #bd362f);
    background-repeat: repeat-x;
    filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffbd362f', GradientType=0);
    border-color: #bd362f #bd362f #802420;
    border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
    filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
}

 

后台截图:

140114后台关键词管理.png


后台代码(采用文本文件来存储关键词的)

<%@  language="VBSCRIPT" codepage="936" %>
<!--#include file="../Inc/Conn.asp"-->
<!--#include file="../Inc/Function.asp"-->
<%AccessControl"IOA"%>
<%
' DCC @ 2014-01-14 10:45:45
if request("work")="addlist" then
     
    ct = vbsUnEscape(request("ct"))
         
    filepath = Server.MapPath("dvKwlist.db.txt")
    set fileConn = Server.CreateObject("Scripting.FileSystemObject")
    set fileOpen = fileConn.OpenTextfile(filepath,8,true)'1读2写8追加
    fileOpen.WriteLine(ct)
    fileOpen.close
     
    response.write "success!"
    response.end()
end if
%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
<title>管理后台</title>
<link type="text/css" rel="stylesheet" id="skin" href="../AdminSkin/<%=session("Admin_Skin")%>/main.css" />
<link type="text/css" rel="stylesheet" id="common" href="../AdminSkin/common.css" />
<script type="text/javascript" src="../AdminSkin/j.js?v=1.83"></script>
     
<script type="text/JavaScript">
// jquery
$(function(){
    var $btn = $('.dv-btn');
    var $ta  = $('.dv-ta');
    var $frm = $('#kwlist');
    var frm_src = $frm.attr('src');
         
             
    // 开始添加 @ 2014-01-14 10:42:44
    $btn.click(function(){
        var ct = $ta.val();
        if( ct=='' ){
            alert('添加的内容不能为空');
            $ta.focus();// 将光标置入输入框
            return;
        }
        $ta.val('');// 清空输入框
        ct = $.trim(ct);
             
        $.get('dv-message-kwlist.asp', {work:'addlist', ct:escape(ct)}, function(d){
            //alert(d);
            $frm.attr('src', frm_src+'?t='+new Date().getTime());
        });
    });
         
});
</script>
     
<style type="text/css">
.dv-main{
    width:800px;
    margin:10px auto;
}
.dv-l{
    float:left;
    width:280px;
}
.dv-r{
    float:right;
    width:500px;
}
.dv-l h2, .dv-r h2{margin:0;}
.dv-ta{
    width:100%;
}
.ta-c{
    text-align:center;
}
</style>
     
</head>
<body class="mainFrameBody">
     
<div class="mainFrameTag"><strong>在线问答 > <a href="/Admin/IOA/dv-message-kwlist.asp">关键词智能匹配列表</a>&nbsp;&nbsp;</strong></div>
<div class="mainFrameContent">
    <div class="dv-main">
        <div style="color:#aaa;">
            <p>使用在线问答的同学越来越多了。在线问答经常会遇到重复的问题。为解决以上问题、提高问答效率,特开发<strong>关键词智能匹配模块</strong>。</p>
            <p>该模块的作用是:用户在输入问答信息后准备点击提交时,通过此处定义的关键词列表,系统提取用户输入的内容进行关键词智能匹配,并在后台异步查询已有相关问答后返回给用户,这样能够在一定程度上降低问题重复率。</p>
        </div>
         
        <div class="dv-l">
            <h2>添加关键词(每行一个):</h2>
            <textarea rows="25" class="dv-ta"></textarea>
            <center><input type="button" class="dv-btn" value="添加新关键词" /></center>
        </div>
             
        <div class="dv-r">
            <h2>已有关键词(新添加的在最后面):</h2>
            <div style="border:1px solid #444;height:381px;"><iframe src="/Admin/IOA/dvKwlist.db.txt" id="kwlist" width="100%" height="100%" frameborder="0"></iframe></div>
        </div>
    <!-- <a style="color:#dcc;font-size:12px;" href="http://www.thinkful.cn/?d=dev">DCC @ 2014-01-14 11:37:07</a> -->
    </div>
</div>
     
</body>
</html>
<%closeConn%>

 



声明: 本文由大超超。原创编译,转载请保留链接: http://www.thinkful.cn/archives/385.html