Python分詞工具——jieba

jieba簡介

  python在數據挖掘領域的使用愈來愈普遍。想要使用python作文本分析,分詞是必不可少的一個環節在python的第三方包裏,jieba應該算得上是分詞領域的佼佼者。html

GitHub地址:https://github.com/fxsjy/jiebapython

安裝方法git

# 全自動安裝:
easy_install jieba 或者 pip install jieba / pip3 install jieba

# 半自動安裝:
先下載 http://pypi.python.org/pypi/jieba/ ,解壓後運行 python setup.py install

# 手動安裝:
將 jieba 目錄放置於當前目錄或者 site-packages 目錄

 

主要算法github

  • 基於前綴詞典實現高效的詞圖掃描,生成句子中漢字全部可能成詞狀況所構成的有向無環圖 (DAG)
  • 採用了動態規劃查找最大機率路徑, 找出基於詞頻的最大切分組合
  • 對於未登陸詞,採用了基於漢字成詞能力的 HMM 模型,使用了 Viterbi 算法

 

特色正則表達式

  • 支持三種分詞模式:算法

    • 精確模式,試圖將句子最精確地切開,適合文本分析;
    • 全模式,把句子中全部的能夠成詞的詞語都掃描出來, 速度很是快,可是不能解決歧義;
    • 搜索引擎模式,在精確模式的基礎上,對長詞再次切分,提升召回率,適合用於搜索引擎分詞。
  • 支持繁體分詞app

  • 支持自定義詞典ide

  • MIT 受權協議函數

 

主要功能工具

  1. 分詞:將句子按指定模式分紅相應的詞彙
  2. 添加自定義詞典:某些詞彙(例如太和殿、臺中、創新辦)可能沒法作到精準分詞,將他們加入自定義詞典,使分詞時更加準確
  3. 關鍵詞提取:獲得句子中出現次數較多的詞彙及它們出現的次數
  4. 去除停用詞
  5. 詞性標註:標註句子分詞後每一個詞的詞性,採用和 ictclas 兼容的標記法。
  6. 並行分詞:將目標句子按行分隔後把各行文本分配到多個 Python 進程並行分詞,而後歸併結果,從而得到分詞速度的可觀提高(目前暫不支持Windows
  7. Tokenize:返回詞語在原文的起止位置(注意,輸入參數只接受 unicode
  8. ChineseAnalyzer for Whoosh 搜索引擎
  9. 命令行分詞

咱們用到的主要是前4個功能,下面就每一個功能具體詳述

 

1、分詞

 5個方法:

  • jieba.cut方法——接受三個輸入參數: 須要分詞的字符串;cut_all 參數用來控制是否採用全模式;HMM 參數用來控制是否使用 HMM 模型
  • jieba.lcut方法 ——做用同上,不一樣點是cut返回的是一個可迭代的 generator,而lcut返回的是一個 list
  • jieba.cut_for_search方法——接受兩個參數:須要分詞的字符串;是否使用 HMM 模型。該方法適合用於搜索引擎構建倒排索引的分詞,粒度比較細
  • jieba.lcut_for_search方法  ——做用同上,不一樣點是cut_for_search返回的是一個可迭代的 generator,而cut_for_search返回的是一個 list
  • jieba.Tokenizer(dictionary=DEFAULT_DICT)—— 新建自定義分詞器,可用於同時使用不一樣詞典。jieba.dt 爲默認分詞器,全部全局分詞相關函數都是該分詞器的映射。

注意:待分詞的字符串能夠是 unicode 或 UTF-8 字符串、GBK 字符串。注意:不建議直接輸入 GBK 字符串,可能沒法預料地錯誤解碼成 UTF-8

示例代碼

# encoding=utf-8
import jieba

# 精確模式:試圖將句子最精確地切開,適合文本分析;
seg_list = jieba.cut("我來到北京清華大學", cut_all=False)
print("精確模式:", "/ ".join(seg_list)) # 精確模式: 我/ 來到/ 北京/ 清華大學

# 默認是精確模式
seg_list = jieba.cut("他來到了網易杭研大廈")
print("默認模式:", "/ ".join(seg_list)) # 默認模式: 他/ 來到/ 了/ 網易/ 杭研/ 大廈

# 全模式:把句子中全部的能夠成詞的詞語都掃描出來, 速度很是快,可是不能解決歧義問題;
seg_list = jieba.cut("我來到北京清華大學", cut_all=True)
print("全模式:", "/ ".join(seg_list)) # 全模式: 我/ 來到/ 北京/ 清華/ 清華大學/ 華大/ 大學

# 搜索引擎模式:在精確模式的基礎上,對長詞再次切分,提升召回率,適合用於搜索引擎分詞。
seg_list = jieba.cut_for_search("小明碩士畢業於中國科學院計算所,後在日本京都大學深造")
print("搜索引擎模式:", "/ ".join(seg_list)) # 搜索引擎模式: 小明/ 碩士/ 畢業/ 於/ 中國/ 科學/ 學院/ 科學院/ 中國科學院/ 計算/ 計算所/ ,/ 後/ 在/ 日本/ 京都/ 大學/ 日本京都大學/ 深造

 

2、添加自定義詞典

  開發者能夠指定本身自定義的詞典,以便包含 jieba 詞庫裏沒有的詞。雖然 jieba 有新詞識別能力,可是自行添加新詞能夠保證更高的正確率

用法:

jieba.load_userdict(file_name) # file_name 爲文件類對象或自定義詞典的路徑
# 詞典格式和 dict.txt 同樣,一個詞佔一行;每一行分三部分:詞語、詞頻(可省略)、詞性(可省略),用空格隔開,順序不可顛倒。file_name 若爲路徑或二進制方式打開的文件,則文件必須爲 UTF-8 編碼。
# 詞頻省略時使用自動計算的能保證分出該詞的詞頻。

 

舉例:

首先添加一個userdict.txt

雲計算 5
李小福 2 nr
創新辦 3 i
easy_install 3 eng
好用 300
韓玉賞鑑 3 nz
八一雙鹿 3 nz
臺中
凱特琳 nz
Edu Trust認證 2000
userdict.txt

而後分詞

#encoding=utf-8
from __future__ import print_function, unicode_literals
import sys
sys.path.append("../")
import jieba
jieba.load_userdict("userdict.txt")
import jieba.posseg as pseg

# 使用 add_word(word, freq=None, tag=None) 和 del_word(word) 可在程序中動態修改詞典。
jieba.add_word('石墨烯')
jieba.add_word('凱特琳')
jieba.del_word('自定義詞')

test_sent = (
"李小福是創新辦主任也是雲計算方面的專家; 什麼是八一雙鹿\n"
"例如我輸入一個帶「韓玉賞鑑」的標題,在自定義詞庫中也增長了此詞爲N類\n"
"「臺中」正確應該不會被切開。mac上可分出「石墨烯」;此時又能夠分出來凱特琳了。"
)
words = jieba.cut(test_sent)
print('/'.join(words))

print("="*40)

result = pseg.cut(test_sent)

for w in result:
    print(w.word, "/", w.flag, ", ", end=' ')

print("\n" + "="*40)

terms = jieba.cut('easy_install is great')
print('/'.join(terms))
terms = jieba.cut('python 的正則表達式是好用的')
print('/'.join(terms))

print("="*40)
# test frequency tune
testlist = [
('今每天氣不錯', ('今天', '天氣')),
('若是放到post中將出錯。', ('', '')),
('咱們中出了一個叛徒', ('', '')),
]

for sent, seg in testlist:
    print('/'.join(jieba.cut(sent, HMM=False)))
    word = ''.join(seg)
    print('%s Before: %s, After: %s' % (word, jieba.get_FREQ(word), jieba.suggest_freq(seg, True)))
    print('/'.join(jieba.cut(sent, HMM=False)))
    print("-"*40)
View Code

 

3、關鍵詞提取

  在構建VSM向量空間模型過程或者把文本轉換成數學形式計算中,會須要運用到關鍵詞提取的技術

基本方法:

jieba.analyse.extract_tags(sentence, topKtopK=20, withWeight=False, allowPOS=()) 
'''
1. sentence 爲待提取的文本
2. topK 爲返回幾個 TF/IDF 權重最大的關鍵詞,默認值爲 20
3. withWeight 爲是否一併返回關鍵詞權重值,默認值爲 False
4. allowPOS 僅包括指定詞性的詞,默認值爲空,即不篩選
'''

舉例

乾清宮 3
太和殿 1
午門 1
dict_baidu.txt
#encoding=utf-8
import jieba
import jieba.analyse

#導入自定義詞典
jieba.load_userdict("dict_baidu.txt")

#精確模式
text = "故宮的著名景點包括乾清宮、太和殿和午門等。其中乾清宮很是精美,午門是紫禁城的正門,午門居中向陽。"
seg_list = jieba.cut(text, cut_all=False)
print(u"分詞結果:")
print("/".join(seg_list))

#獲取關鍵詞
tags = jieba.analyse.extract_tags(text, topK=3)
print(u"關鍵詞:")
print(" ".join(tags))

'''
分詞結果:
故宮/的/著名景點/包括/乾清宮/、/太和殿/和/午門/等/。/其中/乾清宮/很是/精美/,/午門/是/紫禁城/的/正門/,/午門/居中/向陽/。
關鍵詞:
午門 乾清宮 著名景點
'''
# 輸出結果以下,其中"午門"出現3次、"乾清宮"出現2次、"著名景點"出現1次,按照順序輸出提取的關鍵詞。若是topK=5,則輸出:"午門 乾清宮 著名景點 太和殿 向陽"。
View Code

 

4、去除停用詞

   在信息檢索中,爲節省存儲空間和提升搜索效率,在處理天然語言數據(或文本)以前或以後會自動過濾掉某些字或詞,這些字或詞即被稱爲Stop Words(停用詞)。這些停用詞都是人工輸入、非自動化生成的,生成後的停用詞會造成一個停用詞表。可是,並無一個明確的停用詞表可以適用於全部的工具。甚至有一些工具是明確地避免使用停用詞來支持短語搜索的。

#encoding=utf-8
import jieba

#去除停用詞
stopwords = {}.fromkeys(['', '包括', '', ''])
text = "故宮的著名景點包括乾清宮、太和殿和午門等。其中乾清宮很是精美,午門是紫禁城的正門。"
segs = jieba.cut(text, cut_all=False)
final = ''
for seg in segs:
    seg = seg.encode('utf-8')
    if seg not in stopwords:
            final += seg
print final
#輸出:故宮著名景點乾清宮、太和殿和午門。其中乾清宮很是精美,午門紫禁城正門。

seg_list = jieba.cut(final, cut_all=False)
print "/ ".join(seg_list)
#輸出:故宮/ 著名景點/ 乾清宮/ 、/ 太和殿/ 和/ 午門/ 。/ 其中/ 乾清宮/ 很是/ 精美/ ,/ 午門/ 紫禁城/ 正門/ 。

 

5、詞性標註

  標註句子分詞後每一個詞的詞性,採用和 ictclas 兼容的標記法。

# 新建自定義分詞器
jieba.posseg.POSTokenizer(tokenizer=None) 
# tokenizer 參數可指定內部使用的 jieba.Tokenizer分詞器。jieba.posseg.dt 爲默認詞性標註分詞器。

用法示例

import jieba.posseg as pseg
words = pseg.cut("我愛北京天安門")
for word, flag in words:
    print('%s %s' % (word, flag))
'''
我 r
愛 v
北京 ns
天安門 ns
'''

關於詞性標註的詳細說明能夠查看一篇很是好的文章:http://www.hankcs.com/nlp/part-of-speech-tagging.html 

 

6、並行分詞

  將目標文本按行分隔後,把各行文本分配到多個 Python 進程並行分詞,而後歸併結果,從而得到分詞速度的可觀提高(基於 python 自帶的 multiprocessing 模塊,目前暫不支持 Windows

用法

jieba.enable_parallel(4) # 開啓並行分詞模式,參數爲並行進程數
jieba.disable_parallel() # 關閉並行分詞模式

舉例

import sys
import time
sys.path.append("../../")
import jieba

jieba.enable_parallel()

url = sys.argv[1]
content = open(url,"rb").read()
t1 = time.time()
words = "/ ".join(jieba.cut(content))

t2 = time.time()
tm_cost = t2-t1

log_f = open("1.log","wb")
log_f.write(words.encode('utf-8'))

print('speed %s bytes/second' % (len(content)/tm_cost))
# 實驗結果:在 4 核 3.4GHz Linux 機器上,對金庸全集進行精確分詞,得到了 1MB/s 的速度,是單進程版的 3.3 倍。
View Code

注意:並行分詞僅支持默認分詞器 jieba.dt 和 jieba.posseg.dt。

 

7、Tokenize:返回詞語在原文的起止位置

  注意:輸入參數只接受 unicode

默認模式

result = jieba.tokenize(u'永和服裝飾品有限公司')
for tk in result:
    print("word %s\t\t start: %d \t\t end:%d" % (tk[0],tk[1],tk[2]))
'''
word 永和                start: 0                end:2
word 服裝                start: 2                end:4
word 飾品                start: 4                end:6
word 有限公司            start: 6                end:10
'''

 

搜索模式

result = jieba.tokenize(u'永和服裝飾品有限公司', mode='search')
for tk in result:
    print("word %s\t\t start: %d \t\t end:%d" % (tk[0],tk[1],tk[2]))
'''
word 永和                start: 0                end:2
word 服裝                start: 2                end:4
word 飾品                start: 4                end:6
word 有限                start: 6                end:8
word 公司                start: 8                end:10
word 有限公司            start: 6                end:10
'''

 

8、ChineseAnalyzer for Whoosh 搜索引擎

  用於中文關鍵字的搜索引擎

舉例

# -*- coding: UTF-8 -*-
# from __future__ import unicode_literals
import sys, os

sys.path.append("../")
from whoosh.index import create_in, open_dir
from whoosh.fields import *
from whoosh.qparser import QueryParser

from jieba.analyse.analyzer import ChineseAnalyzer

# 導入中文分詞工具
analyzer = ChineseAnalyzer()

# 建立搜索引擎
schema = Schema(title=TEXT(stored=True), path=ID(stored=True), content=TEXT(stored=True, analyzer=analyzer))
if not os.path.exists("tmp"):
    os.mkdir("tmp")

ix = create_in("tmp", schema=schema, indexname='indexname') #temp 爲索引建立的地址,indexname爲索引名稱  
# ix = open_dir("tmp") # for read only
writer = ix.writer()

# 添加內容,相似於引擎搜索的庫
writer.add_document(
    title="document1",
    path="/a",
    content="This is the first document we’ve added!"
)

writer.add_document(
    title="document2",
    path="/b",
    content="The second one 你 中文測試中文 is even more interesting! 吃水果"
)

writer.add_document(
    title="document3",
    path="/c",
    content="買水果真後來世博園。"
)

writer.add_document(
    title="document4",
    path="/c",
    content="工信處女幹事每個月通過下屬科室都要親口交代24口交換機等技術性器件的安裝工做"
)

writer.add_document(
    title="document4",
    path="/c",
    content="咱倆交換一下吧。"
)

writer.commit()

################ 以上爲創建索引的過程 ##############
searcher = ix.searcher()
parser = QueryParser("content", schema=ix.schema)

for keyword in ("水果世博園", "", "first", "中文", "交換機", "交換"):
    print("result of ", keyword)
    q = parser.parse(keyword) # 搜索的關鍵字
    results = searcher.search(q)
    for hit in results:
        print(hit.highlights("content"))
    print("=" * 10)

for t in analyzer("個人好朋友是李明;我愛北京天安門;IBM和Microsoft; I have a dream. this is intetesting and interested me a lot"):
    print(t.text)
View Code

 

9、命令行分詞

格式

python -m jieba [options] news.txt > cut_result.txt
# >後面是輸出的文件,若是不指定則默認爲標準輸出
'''
options參數:
  -h, --help            顯示此幫助信息並退出
  -d [DELIM], --delimiter [DELIM]
                        使用 DELIM 分隔詞語,而不是用默認的' / '。
                        若不指定 DELIM,則使用一個空格分隔。
  -p [DELIM], --pos [DELIM]
                        啓用詞性標註;若是指定 DELIM,詞語和詞性之間
                        用它分隔,不然用 _ 分隔
  -D DICT, --dict DICT  使用 DICT 代替默認詞典
  -u USER_DICT, --user-dict USER_DICT
                        使用 USER_DICT 做爲附加詞典,與默認詞典或自定義詞典配合使用
  -a, --cut-all         全模式分詞(不支持詞性標註)
  -n, --no-hmm          不使用隱含馬爾可夫模型
  -q, --quiet           不輸出載入信息到 STDERR
  -V, --version         顯示版本信息並退出

'''

 

其餘

其餘詞典

  1. 佔用內存較小的詞典文件 https://github.com/fxsjy/jieba/raw/master/extra_dict/dict.txt.small

  2. 支持繁體分詞更好的詞典文件 https://github.com/fxsjy/jieba/raw/master/extra_dict/dict.txt.big

下載你所須要的詞典,而後覆蓋 jieba/dict.txt 便可;或者用 jieba.set_dictionary('data/dict.txt.big')

 

常見問題

  1. 模型的數據是如何生成的?

  詳見: https://github.com/fxsjy/jieba/issues/7

 

  2. 「臺中」老是被切成「臺 中」?(以及相似狀況)

  P(臺中) < P(臺)×P(中),「臺中」詞頻不夠致使其成詞機率較低

  解決方法:強制調高詞頻

  jieba.add_word('臺中') 或者 jieba.suggest_freq('臺中', True)

 

  3. 「今每天氣 不錯」應該被切成「今天 天氣 不錯」?(以及相似狀況)

  解決方法:強制調低詞頻

  jieba.suggest_freq(('今天', '天氣'), True)

或者直接刪除該詞 jieba.del_word('今每天氣')

 

  4. 切出了詞典中沒有的詞語,效果不理想?

  解決方法:關閉新詞發現

  jieba.cut('豐田太省了', HMM=False) jieba.cut('咱們中出了一個叛徒', HMM=False)

 

 

 

 

參考:http://www.javashuo.com/article/p-pimewmlu-d.html

參考:https://github.com/fxsjy/jieba

相關文章
相關標籤/搜索