在文本搜索引擎項目中,須要對已排序的文章進行摘要提取,而後與標題,路徑一塊兒封裝成Json數據返回客戶端。所以這裏我本身寫一個自動摘要,來大概完成這個任務。在自動摘要提取過程當中,使用了一個分詞庫:CppJieba分詞庫。所以在頭文件中包含了頭文件 「Application.hpp」。html
思路:ios
一、對文章提取關鍵字。一般,關鍵字可以表明這篇文章的所描述的內容。所以使用CppJieba分詞庫中「Application.hpp」中api extract()進行關鍵字提取。我提取的是前50個,若文章關鍵字不夠50個則取實際個數。關鍵字的結果已經按照權重的順序排序好。api
二、把文章拆分紅句子。這裏是只對中文進行處理(英文道理也同樣),當遇到句號‘ 。’,問號‘ ? ’,感嘆號‘ ! ’,算一句話。把每一句話按順序保存到vector<string>類型的數組sentences中。數組
三、遍歷關鍵字數組,對每個關鍵字在每個句子中查找包含該關鍵字的第一個句子,並把該句子加入到vector<string>類型的數組summary中。app
四、若遍歷到達關鍵字上限或者句子數量到達上限,跳出循環。函數
五、將數組summary中的句子按順序拼接從摘要。搜索引擎
代碼以下:spa
1 #ifndef _AUTOSUMMERY_HPP 2 #define _AUTOSUMMERY_HPP 3 #include"../src/Statistics/src/Application.hpp" 4 #include <string> 5 #include<set> 6 #include <utility> 7 #include<vector> 8 #include<iostream> 9 #include<functional> 10 using namespace std; 11 using namespace CppJieba; 12 class AutoSummary 13 { 14 public: 15 AutoSummary(Application &app,int maxSentenceNum=10)//初始化一個自動摘要對象 16 :maxSentenceNum_(maxSentenceNum), 17 app_(app) 18 {} 19 20 //自動提取摘要 21 string summarizer(string & originTxt,int KEYNUM=50) 22 { 23 vector<pair<string,double> > keywords; 24 app_.extract(originTxt,keywords,KEYNUM); //取文章的前50個關鍵詞,按權重排序 25 vector<string> sentences; //裝載句子的數組 26 getSentences(originTxt,sentences); //把文章拆分紅句子 27 int sentencesNum = sentences.size(); //句子的數量 28 vector<string> summaryRet; //裝包含關鍵字的句子 29 set<int> summarySet; //句子去重 30 set<int>::iterator it; 31 KEYNUM = keywords.size();//若是關鍵字數量小於50則取實際的數量 32 for(int i = 0;i<KEYNUM;i++) 33 { 34 for(int j = 0;j<sentencesNum;j++) 35 { 36 int pos = sentences[j].find(keywords[i].first,0); 37 if(pos!=string::npos) 38 { 39 it = summarySet.find(pos); 40 if(it==summarySet.end()) 41 { 42 summaryRet.push_back(sentences[j]);//向數組添加句子 43 summarySet.insert(j); 44 break; //跳出循環,找下一個關鍵字 45 } 46 } 47 } 48 //跳出循環的條件 49 if(summaryRet.size()>maxSentenceNum_||summaryRet.size()>=sentencesNum) 50 break; 51 } 52 string summaryStr; 53 int i = 0; 54 int num = summaryRet.size(); 55 while(i<num) 56 { 57 summaryStr = summaryStr + sentences[i]+"……"; 58 i++; 59 } 60 61 return summaryStr; 62 } 63 64 private: 65 //將文章拆分紅句子,私有成員函數,在summarizer()中調用 66 void getSentences(const string &originTxt,vector<string> &sentenceVec) 67 { 68 int beg=0,end=0,pos=0,pos1=0; 69 int txtSize = originTxt.size(); 70 while(beg<txtSize&&pos!=string::npos) 71 { 72 if((pos=originTxt.find("。",beg))!=string::npos) 73 { 74 if((pos1=originTxt.find("?",beg))!=string::npos) 75 { 76 pos=((pos<pos1)?pos:pos1); 77 if((pos1=originTxt.find("!",beg))!=string::npos) 78 { 79 pos=((pos<pos1)?pos:pos1); 80 } 81 82 } 83 else if((pos1=originTxt.find("!",beg))!=string::npos) 84 { 85 pos=((pos<pos1)?pos:pos1); 86 } 87 } 88 else if((pos=originTxt.find("?",beg))!=string::npos) 89 { 90 if((pos1=originTxt.find("!",beg))!=string::npos) 91 { 92 pos=((pos<pos1)?pos:pos1); 93 } 94 95 } 96 else if((pos1=originTxt.find("!",beg))!=string::npos) 97 { 98 pos = pos1; 99 } 100 else 101 { 102 break; 103 } 104 if(pos!=-1) 105 { 106 int len = pos-beg; 107 string sentence(originTxt.substr(beg,len)); 108 sentenceVec.push_back(sentence); 109 beg = pos+3; 110 } 111 } 112 } 113 114 private: 115 Application & app_;//分詞庫的引用 116 int maxSentenceNum_;//摘要中的句子數目,由外部傳進。 117 }; 118 #endif
參考:http://www.ruanyifeng.com/blog/2013/03/automatic_summarization.htmlcode