7. Python 结巴中文分词

本文介绍了结巴分词(Jieba)的特点与使用方法,包括三种分词模式、自定义词典的应用、关键词抽取功能及词语定位功能。通过具体代码示例展示了不同模式下分词效果,自定义词典调整技巧,以及如何进行关键词提取和获取词语在原文中的位置。
摘要由CSDN通过智能技术生成

结巴中文分词

此文档只是作为对 jieba 分词学习的一个记录,详情请参见 jieba 中文分词文档


1. 特点

  • 支持三种分词模式
    • 精确模式:试图将句子最精确的分开
    • 全模式:把剧终中所有的可以成词的词语都扫描出来,速度非常快,但是不能解决歧义
    • 搜索引擎模式:在精确模式的基础之上,对长词再次切分,提高召回率,适合用于搜索引擎
  • 支持繁体分词
  • 支持自定义词典
  • MIT 授权协议

开源协议

代码示例

"""
jieba 中文分词
"""
logger = initiate_log()

# def __init__(self):
#     self.logger = initiate_log()

def get_split_line(self, topic):
    return '='*30 + topic + '='*30

def test_split_mode(self):
    """
    分词模式
    """
    topic = '分词模式'
    split_line = self.get_split_line(topic)
    self.logger.debug(split_line)
    """
    全模式:把句子中所有的金额已成词的词语都扫描出来,速度非常快,但不能解决歧义
    """
    seg_list = jieba.cut("中华人民共和国", cut_all=True)
    self.logger.info("{topic}_全模式: {msg}".format(topic=topic, msg="/ ".join(seg_list)))

    """
    精确模式:试图将句子最精确的切开,适合文本分析
    """
    seg_list = jieba.cut("中华人民共和国", cut_all=False)
    self.logger.info("{topic}_精确模式(默认): {msg}".format(topic=topic, msg="/".join(seg_list)))

    """
    搜索模式:在精确模式的基础上,对长词再次切分,提高召回率,适合用于搜索引擎分词
    """
    seg_list = jieba.cut_for_search("中华人民共和国")
    self.logger.info("{topic}_搜索模式: {msg}".format(topic=topic, msg=", ".join(seg_list)))
2017-10-27 11:10:58,940 root|test_split_mode|INFO|分词模式_全模式: 中华/ 中华人民/ 中华人民共和国/ 华人/ 人民/ 人民共和国/ 共和/ 共和国
2017-10-27 11:10:58,940 root|test_split_mode|INFO|分词模式_精确模式(默认): 中华人民共和国
2017-10-27 11:10:58,941 root|test_split_mode|INFO|分词模式_搜索模式: 中华, 华人, 人民, 共和, 共和国, 中华人民共和国

2. 自定义词典

  • 可以通过 jieba.load_userdict(file_name) 来自定义词典。
  • 可以通过 add_word(word, freq=None, tag=None)del_word(word) 来动态调整词典
  • 可以通过 suggest_freq(segment, tune=True) 可调节单个词语的词频,使其能(或不能)被分出来。

    Note: 自动计算的词频在使用 HMM 新词发现功能时可能无效。


代码示例
def test_user_dict(self):
    """
    2. 自定义词典
    """
    topic = '添加自定义词典'
    split_line = self.get_split_line(topic)
    self.logger.debug(split_line)
    test_sent = """李小福是创新办主任也是云计算方面的专家; 什么是八一双鹿\n
    例如我输入一个带“韩玉赏鉴”的标题,在自定义词库中也增加了此词为N类\n
    台中」正確應該不會被切開。mac上可分出「石墨烯」;此時又可以分出來凱特琳了。
    """
    words = jieba.cut(test_sent)
    self.logger.debug('{topic}_原始: {msg}'.format(topic=topic, msg='/'.join(words)))

    """
            调整词典:动态修改词典
            """
    userdict_path = os.path.dirname(__file__) + "/jieba_dict/dict.txt"
    jieba.add_word('石墨烯')
    jieba.add_word('凱特琳')
    jieba.del_word('自定义词')
    jieba.load_userdict(userdict_path)
    words = jieba.cut(test_sent)
    self.logger.debug('{topic}_自定义字典分词:{msg}'.format(topic=topic, msg='/'.join(words)))

    self.logger.debug('test split words' + "=" * 40)
    terms = jieba.cut('easy_install is great')
    self.logger.debug('{topic}_字典分词: {msg}'.format(topic=topic, msg='/'.join(terms)))
    jieba.del_word('easy_install')
    terms = jieba.cut('easy_install is great')
    self.logger.debug('{topic}_删除单词: {msg}'.format(topic=topic, msg='/'.join(terms)))
    terms = jieba.cut('python 的正则表达式是好用的')
    self.logger.debug('{topic}_单词: {msg}'.format(topic=topic, msg='/'.join(terms)))

    self.logger.debug('test frequency tune' + "=" * 40)
    word = '这里中将应该被切开'
    self.logger.debug('{topic}_调低词频之前: {msg}'.format(topic=topic, msg='/'.join(jieba.cut(word))))
    self.logger.debug('{topic}_调整词频: {msg}'.format(
        topic=topic,
        msg='before: {before}, after: {after}'.format(
            before=jieba.get_FREQ('中将'),
            after=jieba.suggest_freq(('中', '将'), True))))
    self.logger.debug('{topic}_调低词频之后: {msg}'.format(topic=topic, msg='/'.join(jieba.cut(word, HMM=False))))

    jieba.del_word('台中')
    word = '[台中]正确应该不会被切开'
    self.logger.debug('{topic}_调高词频之前: {msg}'.format(topic=topic, msg='/'.join(jieba.cut(word))))
    self.logger.debug('{topic}_调整词频: {msg}'.format(
        topic=topic,
        msg='before: {before}, after: {after}'.format(
            before=jieba.get_FREQ('台中'),
            after=jieba.suggest_freq('台中', True))))
    self.logger.debug('{topic}_调高词频之后: {msg}'.format(topic=topic, msg='/'.join(jieba.cut(word, HMM=False))))
2017-10-27 11:11:46,479 root|test_user_dict|DEBUG|添加自定义词典_原始: 李小福/是/创新/办/主任/也//云/计算/方面//专家/;/ /什么//八/一双/鹿/
/
/ / / / / / / / /例如//输入/一个/带//韩玉/赏鉴/”//标题//在/自定义词/库中//增加//此/词为/N/类/
/

/ / / / / / / / /台//」/正確/應該/不會/被/切開/。/mac//可/分出/「/石墨/烯//;/此時/又/可以/分出/來凱/特琳//。/
/ / / / / / / /
2017-10-27 11:11:46,480 root|test_user_dict|DEBUG|添加自定义词典_自定义字典分词:李小福/是/创新办/主任//是/云计算/方面//专家/;/ /什么//八一双鹿/
/
/ / / / / / / / /例如//输入/一个/带//韩玉赏鉴//的/标题/,//自定义/词库/中//增加//此/词为/N/类/

/
/ / / / / / / / /台中//正確/應該/不會//切開//mac//可/分出/「/石墨烯/」//此時//可以/分出/來/凱特琳/了/。/
/ / / / / / / /
2017-10-27 11:11:46,480 root|test_user_dict|DEBUG|test split words========================================
2017-10-27 11:11:46,480 root|test_user_dict|DEBUG|添加自定义词典_字典分词: easy_install/ /is/ /great
2017-10-27 11:11:46,480 root|test_user_dict|DEBUG|添加自定义词典_删除单词: easy/_/install/ /is/ /great
2017-10-27 11:11:46,480 root|test_user_dict|DEBUG|添加自定义词典_单词: python/ /的/正则表达式/是/好用/的
2017-10-27 11:11:46,480 root|test_user_dict|DEBUG|test frequency tune========================================
2017-10-27 11:11:46,480 root|test_user_dict|DEBUG|添加自定义词典_调低词频之前: 这里/中将/应该/被/切开
2017-10-27 11:11:46,480 root|test_user_dict|DEBUG|添加自定义词典_调整词频: before: 763, after: 494
2017-10-27 11:11:46,480 root|test_user_dict|DEBUG|添加自定义词典_调低词频之后: 这里/中//应该/被/切开
2017-10-27 11:11:46,480 root|test_user_dict|DEBUG|添加自定义词典_调高词频之前: [/台//]/正确/应该/不会/被/切开
2017-10-27 11:11:46,480 root|test_user_dict|DEBUG|添加自定义词典_调整词频: before: 0, after: 69
2017-10-27 11:11:46,481 root|test_user_dict|DEBUG|添加自定义词典_调高词频之后: [/台中/]/正确/应该/不会/被/切开

3. 关键词抽取

  • 通过 jieba.analyse.extract_tags(sentence, topK=20, withWeight=False, allowPOS=())
    • sentence 为待提取的文本
    • topK 为返回几个 TF/IDF 权重最大的关键词,默认值为 20
    • withWeight 为是否一并返回关键词权重值,默认值为 False
    • allowPOS 仅包括指定词性的词,默认值为空,即不筛选
  • jieba.analyse.TFIDF(idf_path=None) 新建 TFIDF 实例,idf_path 为 IDF 频率文件

Note:此处关键词抽取自己没有理解透彻,在自定义语料库的实践上存在问题,没有出现预期的效果。

代码示例

def test_extract_tags(self):
    """
    3. 关键词抽取
    """
    topic = '关键词抽取'
    split_line = self.get_split_line(topic=topic)
    self.logger.info(split_line)

    term = '我们时人中国的可是is of super man'
    res = analyse.extract_tags(term)
    self.logger.info('{topic}_标准抽取: {term} -> {msg}'.format(topic=topic, term=term, msg=res))

    #  TODO: 自定义语料库运行有问题
    user_idf_path = os.path.dirname(__file__) + '/jieba_dict/idf.txt.big'
    analyse.set_idf_path(user_idf_path)
    res = analyse.extract_tags(term)
    self.logger.info('{topic}_自定义逆向文件频率: {term} -> {msg}'.format(topic=topic, term=term, msg=res))
2017-10-27 11:13:07,795 root|test_extract_tags|INFO|关键词抽取_标准抽取: 我们时人中国的可是is of super man -> ['man', 'super', '可是', '我们', '中国']
2017-10-27 11:13:07,822 root|test_extract_tags|INFO|关键词抽取_自定义逆向文件频率: 我们时人中国的可是is of super man -> ['中国', 'man', '可是', '我们', 'super']

4. Tokenize:返回词语在原文的起止位置

Tokenize:返回词语在原文的起止位置

代码示例

def test_tokenize(self):
    """
    Tokenize: 返回词语在原文的位置
    """
    topic = '返回词语在原文的位置'
    split_line = self.get_split_line(topic)
    self.logger.debug(split_line)

    term = '我们都是炎黄子孙'
    res = jieba.tokenize(term)
    for tk in res:
        self.logger.debug('{topic}_默认模式_{term}: {msg}'.format(topic=topic,
                                                         term=term,
                                                         msg="word %s\t\t start: %d \t\t end:%d" % (
                                                         tk[0], tk[1], tk[2])))

    res = jieba.tokenize(term, mode='search')
    for tk in res:
        self.logger.debug('{topic}_搜索模式_{term}: {msg}'.format(topic=topic,
                                                         term=term,
                                                         msg="word %s\t\t start: %d \t\t end:%d" % (
                                                         tk[0], tk[1], tk[2])))
2017-10-27 11:13:35,993 root|test_tokenize|DEBUG|返回词语在原文的位置_默认模式_我们都是炎黄子孙: word 我们       start: 0        end:2
2017-10-27 11:13:35,993 root|test_tokenize|DEBUG|返回词语在原文的位置_默认模式_我们都是炎黄子孙: word 都        start: 2        end:3

2017-10-27 11:13:35,994 root|test_tokenize|DEBUG|返回词语在原文的位置_默认模式_我们都是炎黄子孙: word 是        start: 3        end:4
2017-10-27 11:13:35,994 root|test_tokenize|DEBUG|返回词语在原文的位置_默认模式_我们都是炎黄子孙: word 炎黄子孙         start: 4        end:8
2017-10-27 11:13:35,994 root|test_tokenize|DEBUG|返回词语在原文的位置_搜索模式_我们都是炎黄子孙: word 我们       start: 0        end:2
2017-10-27 11:13:35,994 root|test_tokenize|DEBUG|返回词语在原文的位置_搜索模式_我们都是炎黄子孙: word 都        start: 2        end:3
2017-10-27 11:13:35,994 root|test_tokenize|DEBUG|返回词语在原文的位置_搜索模式_我们都是炎黄子孙: word 是        start: 3        end:4
2017-10-27 11:13:35,994 root|test_tokenize|DEBUG|返回词语在原文的位置_搜索模式_我们都是炎黄子孙: word 炎黄       start: 4        end:6
2017-10-27 11:13:35,994 root|test_tokenize|DEBUG|返回词语在原文的位置_搜索模式_我们都是炎黄子孙: word 子孙       start: 6        end:8
2017-10-27 11:13:35,994 root|test_tokenize|DEBUG|返回词语在原文的位置_搜索模式_我们都是炎黄子孙: word 炎黄子孙         start: 4        end:8

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值