您的位置:首页 > 其它

自动提取文章摘要AutoSummary

2015-10-10 12:57 579 查看
  在文本搜索引擎项目中,需要对已排序的文章进行摘要提取,然后与标题,路径一起封装成Json数据返回客户端。因此这里我自己写一个自动摘要,来大概完成这个任务。在自动摘要提取过程中,使用了一个分词库:CppJieba分词库。因此在头文件中包含了头文件 “Application.hpp”。

思路:

  1、对文章提取关键字。通常,关键字能够代表这篇文章的所描述的内容。因此使用CppJieba分词库中“Application.hpp”中api extract()进行关键字提取。我提取的是前50个,若文章关键字不够50个则取实际个数。关键字的结果已经按照权重的顺序排序好。

  2、把文章拆分成句子。这里是只对中文进行处理(英文道理也一样),当遇到句号‘ 。’,问号‘ ? ’,感叹号‘ ! ’,算一句话。把每一句话按顺序保存到vector<string>类型的数组sentences中。

  3、遍历关键字数组,对每一个关键字在每一个句子中查找包含该关键字的第一个句子,并把该句子加入到vector<string>类型的数组summary中。

  4、若遍历到达关键字上限或者句子数量到达上限,跳出循环。

  5、将数组summary中的句子按顺序拼接从摘要。

代码如下:

#ifndef _AUTOSUMMERY_HPP
#define _AUTOSUMMERY_HPP
#include"../src/Statistics/src/Application.hpp"
#include <string>
#include<set>
#include <utility>
#include<vector>
#include<iostream>
#include<functional>
using namespace std;
using namespace CppJieba;
class AutoSummary
{
public:
AutoSummary(Application &app,int maxSentenceNum=10)//初始化一个自动摘要对象
:maxSentenceNum_(maxSentenceNum),
app_(app)
{}

//自动提取摘要
string summarizer(string & originTxt,int KEYNUM=50)
{
vector<pair<string,double> > keywords;
app_.extract(originTxt,keywords,KEYNUM);    //取文章的前50个关键词,按权重排序
vector<string> sentences;            //装载句子的数组
getSentences(originTxt,sentences);        //把文章拆分成句子
int sentencesNum = sentences.size();        //句子的数量
vector<string> summaryRet;                    //装包含关键字的句子
set<int> summarySet;                        //句子去重
set<int>::iterator it;
KEYNUM = keywords.size();//如果关键字数量小于50则取实际的数量
for(int i = 0;i<KEYNUM;i++)
{
for(int j = 0;j<sentencesNum;j++)
{
int pos = sentences[j].find(keywords[i].first,0);
if(pos!=string::npos)
{
it = summarySet.find(pos);
if(it==summarySet.end())
{
summaryRet.push_back(sentences[j]);//向数组添加句子
summarySet.insert(j);
break;    //跳出循环,找下一个关键字
}
}
}
//跳出循环的条件
if(summaryRet.size()>maxSentenceNum_||summaryRet.size()>=sentencesNum)
break;
}
string summaryStr;
int i = 0;
int num  = summaryRet.size();
while(i<num)
{
summaryStr = summaryStr + sentences[i]+"……";
i++;
}

return summaryStr;
}

private:
//将文章拆分成句子,私有成员函数,在summarizer()中调用
void getSentences(const string &originTxt,vector<string> &sentenceVec)
{
int beg=0,end=0,pos=0,pos1=0;
int txtSize = originTxt.size();
while(beg<txtSize&&pos!=string::npos)
{
if((pos=originTxt.find("。",beg))!=string::npos)
{
if((pos1=originTxt.find("?",beg))!=string::npos)
{
pos=((pos<pos1)?pos:pos1);
if((pos1=originTxt.find("!",beg))!=string::npos)
{
pos=((pos<pos1)?pos:pos1);
}

}
else if((pos1=originTxt.find("!",beg))!=string::npos)
{
pos=((pos<pos1)?pos:pos1);
}
}
else if((pos=originTxt.find("?",beg))!=string::npos)
{
if((pos1=originTxt.find("!",beg))!=string::npos)
{
pos=((pos<pos1)?pos:pos1);
}

}
else if((pos1=originTxt.find("!",beg))!=string::npos)
{
pos = pos1;
}
else
{
break;
}
if(pos!=-1)
{
int len = pos-beg;
string sentence(originTxt.substr(beg,len));
sentenceVec.push_back(sentence);
beg = pos+3;
}
}
}

private:
Application & app_;//分词库的引用
int maxSentenceNum_;//摘要中的句子数目,由外部传进。
};
#endif


参考:http://www.ruanyifeng.com/blog/2013/03/automatic_summarization.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: