① 「關鍵詞」提取都有哪些方案
僅從詞語角度分析,1.2句banana是重復出現的,3.4句kitten是重復出現的。但其實可以發現1.2句主要跟食物有關,3.4句主要跟動物有關,而food、animal兩個詞在四句話里均未出現,有沒有可能判斷出四句話中所包含的兩個主題呢,或者當兩篇文章共有的高頻詞很少,如一篇講banana,一篇講orange,是否可以判斷兩篇文章都包含food這個主題呢,如何生成主題、如何分析文章的主題,這就是topic-model所研究的內容。對文本進行LSA(隱形語義分析)。在直接對詞頻進行分析的研究中,可以認為通過詞語來描述文章,即一層的傳遞關系。而topic-model則認為文章是由主題組成,文章中的詞,是以一定概率從主題中選取的。不同的主題下,詞語出現的概率分布是不同的。比如」魚雷「一詞,在」軍事「主題下出現的概率遠大於在」食品」主題下出現的概率。即topic-model認為文檔和詞語之間還有一層關系。首先假設每篇文章只有一個主題z,則對於文章中的詞w,是根據在z主題下的概率分布p(w|z)生成的。則在已經選定主題的前提下,整篇文檔產生的概率是而這種對每篇文章只有一個主題的假設顯然是不合理的,事實上每篇文章可能有多個主題,即主題的選擇也是服從某概率分布p(t)的因此根據LDA模型,所有變數的聯合分布為表示topic下詞的分布,表示文檔下topic的分布。是第m個文檔的單詞總數。和表示詞語和topic的概率分布先驗參數。而學習LDA的過程,就是通過觀察到的文檔集合,學習的過程。
② 關鍵詞怎麼提取
在巨量的信息面前,很多信息是我們無法全面接收,因此我們需要從中篩選出一些我們感興趣的或者有代表性的信息進行接收。那麼這一個過程就是關鍵詞提取技術。如果我們可以准確的將所有的文檔都用幾個簡單的關鍵詞描述,那麼我們便可以通過關鍵詞了解一篇文章的內容,這將會提高信息獲取到效率。想要在海量的信息里提取出我們所需要的信息,就需要學會如何提取關鍵詞。
二,在上述的TF-IDF演算法中,都需要基於一個現成的語料庫,主題模型的關鍵詞提取演算法則是需要通過對大規模文檔學習,發現文檔的隱含主題。
三,而TextRank演算法則是可以脫離語料庫的基礎,僅對單篇文檔進行分析就可以提取該文檔的關鍵詞。這也是TextRank演算法的重要特點。TextRank演算法的基本思想源於Google的PageRank演算法。因此這里需要先了解下PageRank演算法。
③ TFIDF演算法實現關鍵詞抽取
其實這是一個很簡單的演算法。
先來學習一下概念:
在實際的使用過程中,實際上先使用歷史存量數據計算出每個詞的IDF值,作為一個原始信息,在對新內容進行處理時,只需要計算出TF值就可以了,然後對這篇內容的所有詞計算出TFIDF值,然後進行排序就ok了。
TFIDF是一種十分簡單的關鍵詞提取方案,在實際的應用中,還可以進行多種演算法的融合,之後我再慢慢介紹。
當然了,該演算法還有一些變種,基本上基於下面幾種方法,有興趣的可以了解一下。
④ jieba分詞詳解
「結巴」分詞是一個Python 中文分片語件,參見 https://github.com/fxsjy/jieba
可以對中文文本進行 分詞、詞性標注、關鍵詞抽取 等功能,並且支持自定義詞典。
本文包括以下內容:
1、jieba分詞包的 安裝
2、jieba分詞的 使用教程
3、jieba分詞的 工作原理與工作流程
4、jieba分詞所涉及到的 HMM、TextRank、TF-IDF等演算法介紹
可以直接使用pip來進行安裝:
sudo pip install jieba
或者
sudo pip3 install jieba
關鍵詞抽取有兩種演算法,基於TF-IDF和基於TextRank:
jieba分詞有三種不同的分詞模式: 精確模式、全模式和搜索引擎模式 :
對應的,函數前加l即是對應得到list結果的函數:
精確模式是最常用的分詞方法,全模式會將句子中所有可能的詞都列舉出來,搜索引擎模式則適用於搜索引擎使用。具體的差別可在下一節工作流程的分析中詳述。
在上述每個函數中,都有名為HMM的參數。這一項表示是否在分詞過程中利用HMM進行新詞發現。關於HMM,本文附錄中將簡述相關知識。
另外分詞支持自定義字典,詞典格式和 dict.txt 一樣,一個詞佔一行;每一行分三部分:詞語、詞頻(可省略)、詞性(可省略),用空格隔開,順序不可顛倒。
具體使用方法為:
關鍵詞抽取的兩個函數的完整參數為:
可以通過
來打開或關閉並行分詞功能。
個人感覺一般用不到,大文件分詞需要手動實現多進程並行,句子分詞也不至於用這個。
jieba分詞主要通過詞典來進行分詞及詞性標注,兩者使用了一個相同的詞典。正因如此,分詞的結果優劣將很大程度上取決於詞典,雖然使用了HMM來進行新詞發現。
jieba分詞包整體的工作流程如下圖所示:
下面將根據源碼詳細地分析各個模塊的工作流程。
在之後幾節中,我們在 藍色的方框 中示範了關鍵步驟的輸出樣例或詞典文件的格式樣例。在本節中都採用類似的表示方式。
jieba分詞中,首先通過對照典生成句子的 有向無環圖 ,再根據選擇的模式不同,根據詞典 尋找最短路徑 後對句子進行截取或直接對句子進行截取。對於未登陸詞(不在詞典中的詞)使用 HMM 進行新詞發現。
詞典的格式應為
word1 freq1 word_type1
word2 freq2 word_type2
…
其中自定義用戶詞典中詞性word_type可以省略。
詞典在其他模塊的流程中可能也會用到,為方便敘述,後續的流程圖中將會省略詞典的初始化部分。
圖b演示了搜索引擎模式的工作流程,它會在精確模式分詞的基礎上,將長詞再次進行切分。
在這里我們假定讀者已經了解HMM相關知識,如果沒有可先行閱讀下一章內容中的HMM相關部分或者跳過本節。
在jieba分詞中,將字在詞中的位置B、M、E、S作為隱藏狀態,字是觀測狀態,使用了詞典文件分別存儲字之間的表現概率矩陣(finalseg/prob_emit.py)、初始概率向量(finalseg/prob_start.py)和轉移概率矩陣(finalseg/prob_trans.py)。這就是一個標準的 解碼問題 ,根據概率再利用 viterbi演算法 對最大可能的隱藏狀態進行求解。
詞性分析部分與分詞模塊用了同一個基礎的分詞器,對於詞典詞的詞性,將直接從詞典中提取,但是對於新詞,詞性分析部分有一個 專屬的新詞及其詞性的發現模塊 。
用於詞性標注的HMM模型與用於分詞的HMM模型相似,同樣將文字序列視為可見狀態,但是隱藏狀態不再是單單的詞的位置(B/E/M/S),而變成了詞的位置與詞性的組合,如(B,v)(B,n)(S,n)等等。因此其初始概率向量、轉移概率矩陣和表現概率矩陣和上一節中所用的相比都要龐大的多,但是其本質以及運算步驟都沒有變化。
具體的工作流程如下圖所示。
jieba分詞中有兩種不同的用於關鍵詞抽取的演算法,分別為TextRank和TF-IDF。實現流程比較簡單,其核心在於演算法本身。下面簡單地畫出實現流程,具體的演算法可以參閱下一章內容。
TextRank方法默認篩選詞性,而TF-IDF方法模型不進行詞性篩選。
在本章中,將會簡單介紹相關的演算法知識,主要包括用於新詞發現的 隱馬爾科夫模型 和 維特比演算法 、用於關鍵詞提取的 TextRank 和 TF-IDF 演算法。
HMM即隱馬爾科夫模型,是一種基於馬爾科夫假設的統計模型。之所以為「隱」,是因為相較於馬爾科夫過程HMM有著未知的參數。在世界上,能看到的往往都是表象,而事物的真正狀態往往都隱含在表象之下,並且與表象有一定的關聯關系。
其中,S、O分別表示狀態序列與觀測序列。
如果讀者還對這部分內容心存疑問,不妨先往下閱讀,下面我們將以一個比較簡單的例子對HMM及解碼演算法進行實際說明與演示,在讀完下一小節之後再回來看這些式子,或許能夠恍然大悟。
下面以一個簡單的例子來進行闡述:
假設小明有一個網友小紅,小紅每天都會在朋友圈說明自己今天做了什麼,並且假設其僅受當天天氣的影響,而當天的天氣也只受前一天天氣的影響。
於小明而言,小紅每天做了什麼是可見狀態,而小紅那裡的天氣如何就是隱藏狀態,這就構成了一個HMM模型。一個HMM模型需要有五個要素:隱藏狀態集、觀測集、轉移概率、觀測概率和初始狀態概率。
即在第j個隱藏狀態時,表現為i表現狀態的概率。式中的n和m表示隱藏狀態集和觀測集中的數量。
本例中在不同的天氣下,小紅要做不同事情的概率也不同, 觀測概率 以表格的形式呈現如下:
其中
除此之外,還需要一個初始狀態概率向量π,它表示了觀測開始時,即t=0時,隱藏狀態的概率值。本例中我們指定 π={0,0,1} 。
至此,一個完整的 隱馬爾科夫模型 已經定義完畢了。
HMM一般由三類問題:
概率計算問題 ,即給定 A,B,π 和隱藏狀態序列,計算觀測序列的概率;
預測問題 ,也成解碼問題,已知 A,B,π 和觀測序列,求最優可能對應的狀態序列;
學習問題 ,已知觀測序列,估計模型的 A,B,π 參數,使得在該模型下觀測序列的概率最大,即用極大似然估計的方法估計參數。
在jieba分詞中所用的是解碼問題,所以此處對預測問題和學習問題不做深入探討,在下一小節中我們將繼續以本節中的例子為例,對解碼問題進行求解。
在jieba分詞中,採用了HMM進行新詞發現,它將每一個字表示為B/M/E/S分別代表出現在詞頭、詞中、詞尾以及單字成詞。將B/M/E/S作為HMM的隱藏狀態,而連續的各個單字作為觀測狀態,其任務即為利用觀測狀態預測隱藏狀態,並且其模型的 A,B,π 概率已經給出在文件中,所以這是一個標準的解碼問題。在jieba分詞中採用了 Viterbi演算法 來進行求解。
Viterbi演算法的基本思想是: 如果最佳路徑經過一個點,那麼起始點到這個點的路徑一定是最短路徑,否則用起始點到這點更短的一條路徑代替這段,就會得到更短的路徑,這顯然是矛盾的;從起始點到結束點的路徑,必然要經過第n個時刻,假如第n個時刻有k個狀態,那麼最終路徑一定經過起始點到時刻n中k個狀態里最短路徑的點 。
將時刻t隱藏狀態為i所有可能的狀態轉移路徑i1到i2的狀態最大值記為
下面我們繼續以上一節中的例子來對viterbi演算法進行闡述:
小明不知道小紅是哪裡人,他只能通過小紅每天的活動來推斷那裡的天氣。
假設連續三天,小紅的活動依次為:「睡覺-打游戲-逛街」,我們將據此計算最有可能的天氣情況。
表示第一天為雨天能夠使得第二天為晴天的概率最大(也就是說如果第二天是晴天在最短路徑上的話,第一天是雨天也一定在最短路徑上,參見上文中Viterbi演算法的基本思想)
此時已經到了最後的時刻,我們開始回溯。
其計算過程示意圖如下圖所示。
)的路徑。
TF-IDF(詞頻-逆文本頻率)是一種用以評估字詞在文檔中重要程度的統計方法。它的核心思想是,如果某個詞在一篇文章中出現的頻率即TF高,並且在其他文檔中出現的很少,則認為這個詞有很好的類別區分能力。
其中:
TextRank是一種用以關鍵詞提取的演算法,因為是基於PageRank的,所以先介紹PageRank。
PageRank通過互聯網中的超鏈接關系確定一個網頁的排名,其公式是通過一種投票的思想來設計的:如果我們計算網頁A的PageRank值,那麼我們需要知道哪些網頁鏈接到A,即首先得到A的入鏈,然後通過入鏈給網頁A進行投票來計算A的PR值。其公式為:
其中:
d為阻尼系數,取值范圍為0-1,代表從一定點指向其他任意點的概率,一般取值0.85。
將上式多次迭代即可直到收斂即可得到結果。
TextRank演算法基於PageRank的思想,利用投票機制對文本中重要成分進行排序。如果兩個詞在一個固定大小的窗口內共同出現過,則認為兩個詞之間存在連線。
公式與PageRank的基本相同。多次迭代直至收斂,即可得到結果。
在jieba分詞中,TextRank設定的詞窗口大小為5,將公式1迭代10次的結果作為最終權重的結果,而不一定迭代至收斂。
⑤ php 要從文章內容,提取關鍵詞,要怎麼寫!
提取關鍵詞,你必須得有個詞庫。然後根據詞庫匹配文章內容。詞庫越多效率越低,文章內容長度越長效率越低。
網上針對php有相乾的分詞演算法,你可以搜
」SCWS
中文分詞「
來看一下。你可以根據裡面的例子來做擴展
⑥ 大數據演算法:分類演算法
KNN演算法,即K近鄰(K Nearest Neighbour)演算法,是一種基本的分類演算法。其主要原理是:對於一個需要分類的數據,將其和一組已經分類標注好的樣本集合進行比較,得到距離最近的K個樣本,K個樣本最多歸屬的類別,就是這個需要分類數據的類別。下面我給你畫了一個KNN演算法的原理圖。
圖中,紅藍綠三種顏色的點為樣本數據,分屬三種類別 、 、 。對於待分類點 ,計算和它距離最近的5個點(即K為5),這5個點最多歸屬的類別為 (4個點歸屬 ,1個點歸屬 ),那麼 的類別被分類為 。
KNN的演算法流程也非常簡單,請看下面的流程圖。
KNN演算法是一種非常簡單實用的分類演算法,可用於各種分類的場景,比如新聞分類、商品分類等,甚至可用於簡單的文字識別。對於新聞分類,可以提前對若干新聞進行人工標注,標好新聞類別,計算好特徵向量。對於一篇未分類的新聞,計算其特徵向量後,跟所有已標注新聞進行距離計算,然後進一步利用KNN演算法進行自動分類。
讀到這你肯定會問,如何計算數據的距離呢?如何獲得新聞的特徵向量呢?
KNN演算法的關鍵是要比較需要分類的數據與樣本數據之間的距離,這在機器學習中通常的做法是:提取數據的特徵值,根據特徵值組成一個n維實數向量空間(這個空間也被稱作特徵空間),然後計算向量之間的空間距離。空間之間的距離計算方法有很多種,常用的有歐氏距離、餘弦距離等。
對於數據 和 ,若其特徵空間為n維實數向量空間 ,即 , ,則其歐氏距離計算公式為
這個歐式距離公式其實我們在初中的時候就學過,平面幾何和立體幾何里兩個點之間的距離,也是用這個公式計算出來的,只是平面幾何(二維幾何)里的n=2,立體幾何(三維幾何)里的n=3,而機器學習需要面對的每個數據都可能有n維的維度,即每個數據有n個特徵值。但是不管特徵值n是多少,兩個數據之間的空間距離的計算公式還是這個歐氏計算公式。大多數機器學習演算法都需要計算數據之間的距離,因此掌握數據的距離計算公式是掌握機器學習演算法的基礎。
歐氏距離是最常用的數據計算公式,但是在文本數據以及用戶評價數據的機器學習中,更常用的距離計算方法是餘弦相似度。
餘弦相似度的值越接近1表示其越相似,越接近0表示其差異越大,使用餘弦相似度可以消除數據的某些冗餘信息,某些情況下更貼近數據的本質。我舉個簡單的例子,比如兩篇文章的特徵值都是:「大數據」「機器學習」和「極客時間」,A文章的特徵向量為(3, 3, 3),即這三個詞出現次數都是3;B文章的特徵向量為(6, 6, 6),即這三個詞出現次數都是6。如果光看特徵向量,這兩個向量差別很大,如果用歐氏距離計算確實也很大,但是這兩篇文章其實非常相似,只是篇幅不同而已,它們的餘弦相似度為1,表示非常相似。
餘弦相似度其實是計算向量的夾角,而歐氏距離公式是計算空間距離。餘弦相似度更關注數據的相似性,比如兩個用戶給兩件商品的打分分別是(3, 3)和(4, 4),那麼兩個用戶對兩件商品的喜好是相似的,這種情況下,餘弦相似度比歐氏距離更合理。
我們知道了機器學習的演算法需要計算距離,而計算距離需要還知道數據的特徵向量,因此提取數據的特徵向量是機器學習工程師們的重要工作,有時候甚至是最重要的工作。不同的數據以及不同的應用場景需要提取不同的特徵值,我們以比較常見的文本數據為例,看看如何提取文本特徵向量。
文本數據的特徵值就是提取文本關鍵詞,TF-IDF演算法是比較常用且直觀的一種文本關鍵詞提取演算法。這種演算法是由TF和IDF兩部分構成。
TF是詞頻(Term Frequency),表示某個單詞在文檔中出現的頻率,一個單詞在一個文檔中出現的越頻繁,TF值越高。
詞頻:
IDF是逆文檔頻率(Inverse Document Frequency),表示這個單詞在所有文檔中的稀缺程度,越少文檔出現這個詞,IDF值越高。
逆文檔頻率:
TF與IDF的乘積就是TF-IDF。
所以如果一個詞在某一個文檔中頻繁出現,但在所有文檔中卻很少出現,那麼這個詞很可能就是這個文檔的關鍵詞。比如一篇關於原子能的技術文章,「核裂變」「放射性」「半衰期」等詞彙會在這篇文檔中頻繁出現,即TF很高;但是在所有文檔中出現的頻率卻比較低,即IDF也比較高。因此這幾個詞的TF-IDF值就會很高,就可能是這篇文檔的關鍵詞。如果這是一篇關於中國原子能的文章,也許「中國」這個詞也會頻繁出現,即TF也很高,但是「中國」也在很多文檔中出現,那麼IDF就會比較低,最後「中國」這個詞的TF-IDF就很低,不會成為這個文檔的關鍵詞。
提取出關鍵詞以後,就可以利用關鍵詞的詞頻構造特徵向量,比如上面例子關於原子能的文章,「核裂變」「放射性」「半衰期」這三個詞是特徵值,分別出現次數為12、9、4。那麼這篇文章的特徵向量就是(12, 9, 4),再利用前面提到的空間距離計算公式計算與其他文檔的距離,結合KNN演算法就可以實現文檔的自動分類。
貝葉斯公式是一種基於條件概率的分類演算法,如果我們已經知道A和B的發生概率,並且知道了B發生情況下A發生的概率,可以用貝葉斯公式計算A發生的情況下B發生的概率。事實上,我們可以根據A的情況,即輸入數據,判斷B的概率,即B的可能性,進而進行分類。
舉個例子:假設一所學校里男生佔60%,女生佔40%。男生總是穿長褲,女生則一半穿長褲一半穿裙子。假設你走在校園中,迎面走來一個穿長褲的學生,你能夠推斷出這個穿長褲學生是男生的概率是多少嗎?
答案是75%,具體演算法是:
這個演算法就利用了貝葉斯公式,貝葉斯公式的寫法是:
意思是A發生的條件下B發生的概率,等於B發生的條件下A發生的概率,乘以B發生的概率,除以A發生的概率。還是上面這個例子,如果我問你迎面走來穿裙子的學生是女生的概率是多少。同樣帶入貝葉斯公式,可以計算出是女生的概率為100%。其實這個結果我們根據常識也能推斷出來,但是很多時候,常識受各種因素的干擾,會出現偏差。比如有人看到一篇博士生給初中學歷老闆打工的新聞,就感嘆讀書無用。事實上,只是少見多怪,樣本量太少而已。而大量數據的統計規律則能准確反映事物的分類概率。
貝葉斯分類的一個典型的應用場合是垃圾郵件分類,通過對樣本郵件的統計,我們知道每個詞在郵件中出現的概率 ,我們也知道正常郵件概率 和垃圾郵件的概率 ,還可以統計出垃圾郵件中各個詞的出現概率 ,那麼現在一封新郵件到來,我們就可以根據郵件中出現的詞,計算 ,即得到這些詞出現情況下,郵件為垃圾郵件的概率,進而判斷郵件是否為垃圾郵件。
現實中,貝葉斯公式等號右邊的概率,我們可以通過對大數據的統計獲得,當有新的數據到來的時候,我們就可以帶入上面的貝葉斯公式計算其概率。而如果我們設定概率超過某個值就認為其會發生,那麼我們就對這個數據進行了分類和預測,具體過程如下圖所示。
訓練樣本就是我們的原始數據,有時候原始數據並不包含我們想要計算的維度數據,比如我們想用貝葉斯公式自動分類垃圾郵件,那麼首先要對原始郵件進行標注,需要標注哪些郵件是正常郵件、哪些郵件是垃圾郵件。這一類需要對數據進行標注才能進行的機器學習訓練也叫作有監督的機器學習。
⑦ TextRank——關鍵詞提取
TextRank 演算法可以脫離語料庫的背景,僅對單篇文檔進行分析就可以提取該文檔的關鍵詞。
TextRank 演算法基於 PageRank 演算法的。 PageRank 演算法是一種網頁排名演算法,其基本思想有兩條:
d 表示阻尼系數,為了解決沒有入鏈網頁的得分。 在 0.85 的阻尼系數下,大約 100 多次迭代 PR 值就能收斂到一個穩定的值,而當阻尼系數接近 1 時,需要的迭代次數會陡然增加很多,且排序不穩定。
鏈接網頁的初始分數如何確定: 演算法開始時會將所有網頁的得分初始化為 1,然後通過多次迭代來對每個網頁的分數進行收斂。收斂時的得分就是網頁最終得分。若不能收斂,也可以通過設定最大迭代次數來對計算進行控制,計算停止時的分數就是網頁的得分。
https://www.zybuluo.com/evilking/note/902585
⑧ 用Py做文本分析5:關鍵詞提取
關鍵詞指的是原始文檔的和核心信息,關鍵詞提取在文本聚類、分類、自動摘要等領域中有著重要的作用。
針對一篇語段,在不加人工干預的情況下提取出其關鍵詞
無監督學習——基於詞頻
思路1:按照詞頻高低進行提取
思路2:按照詞條在文檔中的重要性進行提取
IF-IDF是信息檢索中最常用的一種文本關鍵信息表示法,其基本的思想是如果某個詞在一篇文檔中出現的頻率高,並且在語料庫中其他文檔中很少出現,則認為這個詞具有很好的類別區分能力。
TF:Term Frequency,衡量一個term在文檔中出現得有多頻繁。平均而言出現越頻繁的詞,其重要性可能就越高。考慮到文章長度的差異,需要對詞頻做標准化:
IDF:Inverse Document Frequency,逆文檔概率,用於模擬在該語料的實際使用環境中,目標term的重要性。
TF-IDF:TF*IDF
優點:
(1)jieba
(2)sklearn
(3)gensim
前面介紹的TF-IDF屬於無監督中基於詞頻的演算法,TextRank演算法是基於圖形的演算法。
TextRank演算法的思想來源於PageRank演算法:
和基於詞頻的演算法相比,TextRank進一步考慮了文檔內詞條間的語義關系。
參考資料:
Python數據分析--玩轉文本挖掘
⑨ 求一個提取文章關鍵詞的java程序
//直接粘貼就行。
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Scanner;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JSplitPane;
import javax.swing.JTextArea;
import javax.swing.border.EtchedBorder;
import javax.swing.filechooser.FileFilter;
public class Application2 extends JFrame implements Cloneable{
public Application2(){
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setSize(800,700);
this.setLayout(new BorderLayout());
keyWords1=new String[]{"那麼","還是","sdf"};
keyWords2=new String[]{"所以","而且",};
input=new JTextArea();
JPanel ip=new JPanel();
ip.setLayout(new BorderLayout());
ip.add(input,BorderLayout.CENTER);
ip.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(EtchedBorder.LOWERED), "輸入文本"));
output1=new JTextArea();
JPanel o1p=new JPanel();
o1p.setLayout(new BorderLayout());
o1p.add(output1,BorderLayout.CENTER);
o1p.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(EtchedBorder.LOWERED), "以下為"));
output2=new JTextArea();
JPanel o2p=new JPanel();
o2p.setLayout(new BorderLayout());
o2p.add(output2,BorderLayout.CENTER);
o2p.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(EtchedBorder.LOWERED), "以下為"));
JSplitPane split1=new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,o1p,o2p);
split1.setDividerLocation(350);
JSplitPane split2=new JSplitPane(JSplitPane.VERTICAL_SPLIT,ip,split1);
split2.setDividerLocation(300);
this.add(split2,BorderLayout.CENTER);
open=new JButton("導入");
open.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
JFileChooser chooser=new JFileChooser(".");
chooser.setMultiSelectionEnabled(false);
chooser.addChoosableFileFilter(new FileFilter(){
@Override
public boolean accept(File file) {
if(file.isDirectory())
return true;
int length=file.getName().length();
if(length<5)
return false;
if(file.getName().substring(length-4).equals(".txt"))
return true;
return false;
}
@Override
public String getDescription() {
return "文本文件";
}
});
chooser.showOpenDialog(Application2.this);
File file=chooser.getSelectedFile();
if(file==null)
return;
try {
Scanner sc=new Scanner(file);
String text="";
while(sc.hasNextLine())
text+=sc.nextLine()+"\n";
input.setText(text);
String[] array=getSentences();
output1.setText(getKeySentences(keyWords1,array));
output2.setText(getKeySentences(keyWords2,array));
}catch (IOException e1) {
e1.printStackTrace();
}
}
});
save=new JButton("導出");
save.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
JFileChooser chooser=new JFileChooser(".");
chooser.setMultiSelectionEnabled(false);
chooser.addChoosableFileFilter(new FileFilter(){
@Override
public boolean accept(File file) {
if(file.isDirectory())
return true;
int length=file.getName().length();
if(length<5)
return false;
if(file.getName().substring(length-4).equals(".txt"))
return true;
return false;
}
@Override
public String getDescription() {
return "文本文件";
}
});
chooser.showSaveDialog(Application2.this);
File file=chooser.getSelectedFile();
if(file==null)
return;
try {
PrintWriter pw=new PrintWriter(file);
pw.print(output1.getText());
pw.flush();
pw.print(output2.getText());
pw.flush();
}catch (IOException e1) {
e1.printStackTrace();
}
}
});
JPanel buttonPane=new JPanel();
buttonPane.add(open);
buttonPane.add(save);
this.add(buttonPane,BorderLayout.SOUTH);
}
public String[] getSentences(){
ArrayList<String> set=new ArrayList<String>();
int length=input.getText().length();
for(int i=0,last=0;i<length;i++){
String s=String.valueOf(input.getText().charAt(i));
if(s.equals("\n"))
last=i+1;
if(s.equals(".")||s.equals(",")||s.equals("。")||s.equals("。")||s.equals("!")||s.equals("?")||s.equals("?")||s.equals("!")||s.equals(",")){
set.add(input.getText().substring(last,i)+s);
last=i+1;
}
}
return set.<String>toArray(new String[set.size()]);
}
public String getKeySentences(String[] key,String[] sentences){
String result="";
A: for(int i=0;i<sentences.length;i++){
for (int k = 0; k < key.length; k++)
if (sentences[i].contains(key[k].subSequence(0, key[k].length()))) {
result += sentences[i] + "\n";
continue A;
}
}
return result;
}
private JTextArea input;
private JTextArea output1;
private JTextArea output2;
private JButton open;
private JButton save;
private String[] keyWords1;
private String[] keyWords2;
public static void main(String... args){
EventQueue.invokeLater(new Runnable(){
public void run(){
new Application2().setVisible(true);
}
});
}
}