把之前做過的校園新聞小項目拆開來,簡單分析每個部分的功能,希望能給感興趣的童鞋一些借鑑和啓發。純手工打造,尊重原創,轉載必究!
上一篇博客已經談到項目裏服務器程序如何爬取新聞網上的內容,把與新聞相關的文本內容存儲爲文件,與新聞相關的圖片上傳到圖片服務器。在文件處理階段,我需要的是將新聞按時間分類保存到數據庫,並且提取指定時段的關鍵詞存儲爲文件,爲客戶端推送經過分類的新聞,並且在有了關鍵詞之後可以爲給客戶端用戶推薦感興趣的新聞做準備。
這個部分的結構比較簡單,主要是文件讀寫操作和關鍵詞提取。關於文件讀寫值得一提的是,由於新聞需要按時間分類,所以爲了加速找到指定時間的新聞,建立了一層索引文件記錄每條新聞的位置,這就得事先定義好爬蟲後文件存儲格式的協議,索引文件內的格式(一般是(i,j)格式,i代表文件名,j代表數據在這個文件裏的偏移量)。下面主要聊關鍵詞的提取,給大家分享一下使用復旦開源項目 fnlp 的心得。
獲取關鍵詞的大體思路是:將新聞內容(字符串)分詞,去掉停用詞,對剩下的詞做統計,選擇其中出現頻率最多的20個詞作爲關鍵詞,存儲到文件裏。
fnlp的環境配置這裏就不多說了,可以參考他們在github的官方教程,考慮到都是些基礎操作,這裏直接上代碼。
/**
* 統計指定日期所有新聞出現排名前20的熱詞,先分詞,再去除停用詞,排序
* @param news 新聞具體內容
* @return
*/
private void getTop20Words(String news)
{
CNFactory factory;
List<Map.Entry<String, Integer>> sortedWordsList ;
try {
factory = CNFactory.getInstance(mFileReader.getModelPath());
//此過程可能有亂碼出現,暫時不管,程序包有問題
String[] words = factory.seg(news);
//去除停用詞
List<String> noStopWordsStr = mPhraseDel(words);
//對list內的分詞結果統計頻次
CCNWordsCounter wc = new CCNWordsCounter();
for(String s:noStopWordsStr)
{
wc.addWordCount(s);
}
//根據詞的頻次排序
sortedWordsList = sortHashMap(wc.gethMap());
for (int i = 0; i < (19<=sortedWordsList.size()?19:sortedWordsList.size()); i++) {
Entry<String,Integer> ent=sortedWordsList.get(i);
Top20WordsList.add(ent);
}
} catch (LoadModelException e) {
log.info("加載語言處理模型失敗!");
e.printStackTrace();
}
}
/**
* 去除停用詞
* @param words 待處理的詞
* @return 去掉停用詞的列表
*/
private List<String> mPhraseDel(String[] words){
StopWords sw = new StopWords();
sw.read(mFileReader.getStopwordsPath());
List<String> list = new ArrayList<String>();
String s;
int length= words.length;
for(int i = 0; i < length; i++){
s = words[i];
if(!sw.isStopWord(s,2,4))
list.add(s);
}
return list;
}
/**
* 按詞出現的頻率從大到小排序
* @param map <詞,出現的次數>哈希表
* @return 排好序的詞列表
*/
private List sortHashMap(HashMap<String,Integer> map)
{
List<Map.Entry<String, Integer>> infoIds = new ArrayList<Map.Entry<String, Integer>>(
map.entrySet());
// 排序
Collections.sort(infoIds, new Comparator<Map.Entry<String, Integer>>() {
public int compare(Map.Entry<String, Integer> o1,
Map.Entry<String, Integer> o2) {
return ( o2.getValue()-o1.getValue());
}
});
return infoIds;
}
現在就可以get排好序的list列表了,由於文本基數比較少,這樣提取關鍵詞的邏輯顯得比較簡單粗暴,但是可以作爲操作fnlp自然語言處理庫的實踐。