這是一個比較奇葩的需求,先說需求:
微信羣聊,每個人會對boss說的話發表一下自己的感悟,需求就是將這些聊天記錄中重複的部分找出來,也就是把抄襲別人感悟的人找出來。
整體設計:使用springboot開發後臺接口,用戶從微信拿到格式化的數據之後,在前端通過ajax發送http請求把聊天數據post到服務端,服務端進行分析之後返回結果。
1.微信羣聊的格式
通過微信羣聊中的“更多”–>“郵件”功能把聊天記錄格式化出來,在“郵件”功能頁面可以把經過格式化的聊天信息【複製】出來,然後上傳我們的系統進行分析。
經過格式化的微信羣聊信息:
紅框位置是【換行】,藍圈位置是【空格】。
初步分析:需要注意的是聊天記錄中也可能會人爲添加【換行符】,按照【換行符】截斷記錄會出現問題,這種思路走不通。
2.信息提取–>姓名、時間、聊天內容
把上面的已經格式化的信息進行分析:
姓名 [空格] 時間 [換行符]
[換行符]
聊天 [空格] 聊天 [換行符]
聊天 [空格] [換行符]
[換行符]
很顯然應該用【空行】來分割各個信息,即把整條數據按照【[換行符] [換行符]】進行分割,也就是說用兩個【換行符】進行分割,存儲到數組。
所以數組中的內容就是:[姓名+時間],[聊天內容] 這種存儲方式。
同樣這個地方可以判斷數組的length,如果爲奇數,則數據切割出錯。
3.信息存儲–>對象
實例化一個對象用於存儲一條聊天信息。
//微信消息實體類
public class WxMsg {
private int id; //數據庫記錄id
private String name; //言論者
private String timed; //發表言論時間
private String msg; //發表的言論
private int ischeck; //是否已經被檢查
private String islike; //和哪條記錄相似
public WxMsg() {
ischeck=0;
islike=null;
}
get&set()
}
接下來就是把數組中的內容放到對象中,然後把對象存到一個List中。
4.數據轉移:數組–>list
數組中,偶數位元素表示[姓名+時間],顯然要分割提取出姓名、時間。由於姓名的格式存在多樣性,所以應該從時間入手。經過考慮,決定把【姓名+時間】這個字符串從尾部截取5個字符,剩下的字符串去空格,經過這樣操作就可分析出姓名、時間:
【趙 旭東 19:46】–> 【趙旭東】、【19:46】
List<WxMsg> wxMsgList = new ArrayList<WxMsg>();//用於存儲微信信息實體的集合
//按照\n\n分割字符串存進數組 [姓名 時間] [聊天信息]
String[] wxmsg_arr=wxmsgstr.split("\n\n");
if (wxmsg_arr.length%2 == 1){
System.out.println("格式錯誤:"+wxmsg_arr[wxmsg_arr.length-1]);
return "error";
}
//else
System.out.println("共解析出的聊天記錄條數:"+wxmsg_arr.length/2);
//將數組中的信息提取到對象中並存儲
for(int i=0; i<wxmsg_arr.length;i=i+2){
WxMsg wxMsg = new WxMsg();
//取出時間
wxMsg.setTimed(wxmsg_arr[i].substring(wxmsg_arr[i].length()-5));
//取出姓名
wxMsg.setName(wxmsg_arr[i].substring(0,wxmsg_arr[i].length()-6));
//存聊天內容
wxMsg.setMsg(wxmsg_arr[i+1]);
System.out.println("數據轉移arr-list:"+wxMsg.toString());
wxMsgList.add(wxMsg);
}
將每條記錄都存到對象中,然後存儲到list中,那麼list中的數據就是:老的聊天信息在前面,新的聊天信息在後面。
list.get(i); —> i越大,信息越新
5.重複度檢查
這是這個系統的核心,也是後期繼續優化的重點位置,目前沒有采用任何高級算法,只是先實現這個檢查功能。
- 第一步:這也是第一層循環,從後向前遍歷List(i=max –> i=0)。至於爲什麼要從後向前遍歷?一定要先檢查最後一個人說的,檢查的是看當前【被檢查人】和前面的聊天記錄是否重複,第一個發表的人當然不需要檢查。
- 第二步:從list中取出當前對象的一個【聊天記錄】,把這個【聊天記錄】按照各種標點符合進行分割,分割成若干句話,存到數組msg[]中。
- 第三步:第二層循環,循環遍歷存儲當前對象聊天記錄的數組msg[],接下來就是判斷數組中存放的每一句話和list中其他對象的[聊天記錄]是否相似。
- 第四步:第三層循環,遍歷存放對象的list(i=this-1 –> i=0),從【當前對象的位置-1】開始遍歷,一直遍歷到【開頭】,當然這裏遍歷的方向無所謂,重點是要覆蓋當前對象位置之前的記錄。在這層循環中需要判斷上層的msg[i]這句話和那個對象的[聊天記錄相似],如果相似,就進行記錄。
//分析查重
/*
j:當前在被查的人 z:當前被查的人的第幾句話 y:被比對的人()
*/
System.out.println("分析查重測試");
//從新到老把聊天記錄遍歷一遍(最老的數據當然不需要檢查)
for(int j=wxMsgList.size()-1;j>0;j--){
//切分這個人的聊天信息
String[] per_msg = wxMsgList.get(0).getMsg().split("[、,。;?!,.;?\\n]");
//用上面的分析方法,遇上標點加換行會產生空數據
//遍歷這些聊天數據
for(int z=0;z<per_msg.length;z++){
//每句聊天記錄去匹配比他老的聊天信息
for(int y=j-1;y>=0;y--){
if("".equals(per_msg[z])){
//聊天記錄是空的,不匹配
}else {
int rs = wxMsgList.get(y).getMsg().indexOf(per_msg[z]);
if(rs==-1){
}else {
analysestr = analysestr +
wxMsgList.get(j).getName()+"在時間:"+wxMsgList.get(j).getTimed()
+"說的第"+(z+2)+"句(大約)抄襲"+wxMsgList.get(y).getName()
+"在時間:"+wxMsgList.get(y).getTimed()
+"說的第"+rs+"個字往後 <br /> <br />";
System.out.println(analysestr);
}
}
}
}
}