MCPcopy Index your code
hub / github.com/blmoistawinde/HarvestText

github.com/blmoistawinde/HarvestText @V0.8

Chat with this repo
repository ↗ · DeepWiki ↗ · release V0.8 ↗ · + Follow
188 symbols 771 edges 23 files 55 documented · 29% updated 2y agoV0.8 · 2020-10-08★ 2,61917 open issues
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

# HarvestText

Sow with little data seed, harvest much from a text field.

播撒几多种子词,收获万千领域实

GitHub stars PyPI - Python Version GitHub Version Version document

文档

用途

HarvestText是一个专注无(弱)监督方法,能够整合领域知识(如类型,别名)对特定领域文本进行简单高效地处理和分析的库。适用于许多文本预处理和初步探索性分析任务,在小说分析,网络文本,专业文献等领域都有潜在应用价值。

使用案例: - 分析《三国演义》中的社交网络(实体分词,文本摘要,关系网络等) 网络建模过程示意.png - 2018中超舆情展示系统(实体分词,情感分析,新词发现[辅助绰号识别]等) 相关文章:一文看评论里的中超风云 2018中超舆情展示系统

【注:本库仅完成实体分词和情感分析,可视化使用matplotlib】 - 近代史纲要信息抽取及问答系统(命名实体识别,依存句法分析,简易问答系统)

本README包含各个功能的典型例子,部分函数的详细用法可在文档中找到:

文档

具体功能如下:

目录: - 基本处理 - 精细分词分句 - 可包含指定词和类别的分词。充分考虑省略号,双引号等特殊标点的分句。 - 文本清洗 - 处理URL, email, 微博等文本中的特殊符号和格式,去除所有标点等 - 实体链接 - 把别名,缩写与他们的标准名联系起来。 - 命名实体识别 - 找到一句句子中的人名,地名,机构名等命名实体。 - 实体别名自动识别(更新!) - 从大量文本中自动识别出实体及其可能别名,直接用于实体链接。例子见这里 - 依存句法分析 - 分析语句中各个词语(包括链接到的实体)的主谓宾语修饰等语法关系, - 内置资源 - 通用停用词,通用情感词,IT、财经、饮食、法律等领域词典。可直接用于以上任务。 - 信息检索 - 统计特定实体出现的位置,次数等。 - 新词发现 - 利用统计规律(或规则)发现语料中可能会被传统分词遗漏的特殊词汇。也便于从文本中快速筛选出关键词。 - 字符拼音纠错(调整) - 把语句中有可能是已知实体的错误拼写(误差一个字符或拼音)的词语链接到对应实体。 - 自动分段 - 使用TextTiling算法,对没有分段的文本自动分段,或者基于已有段落进一步组织/重新分段 - 存取消除 - 可以本地保存模型再读取复用,也可以消除当前模型的记录。 - 英语支持 - 本库主要旨在支持对中文的数据挖掘,但是加入了包括情感分析在内的少量英语支持 - 高层应用 - 情感分析 - 给出少量种子词(通用的褒贬义词语),得到语料中各个词语和语段的褒贬度。 - 关系网络 - 利用共现关系,获得关键词之间的网络。或者以一个给定词语为中心,探索与其相关的词语网络。 - 文本摘要 - 基于Textrank算法,得到一系列句子中的代表性句子。 - 关键词抽取 - 基于Textrank, tfidf等算法,获得一段文本中的关键词 - 事实抽取 - 利用句法分析,提取可能表示事件的三元组。 - 简易问答系统 - 从三元组中建立知识图谱并应用于问答,可以定制一些问题模板。效果有待提升,仅作为示例。

用法

首先安装, 使用pip ```shell script pip install --upgrade harvesttext


或进入setup.py所在目录,然后命令行:
```shell script
python setup.py install

随后在代码中:

from harvesttext import HarvestText
ht = HarvestText()

即可调用本库的功能接口。

实体链接

给定某些实体及其可能的代称,以及实体对应类型。将其登录到词典中,在分词时优先切分出来,并且以对应类型作为词性。也可以单独获得语料中的所有实体及其位置:

para = "上港的武磊和恒大的郜林,谁是中国最好的前锋?那当然是武磊武球王了,他是射手榜第一,原来是弱点的单刀也有了进步"
entity_mention_dict = {'武磊':['武磊','武球王'],'郜林':['郜林','郜飞机'],'前锋':['前锋'],'上海上港':['上港'],'广州恒大':['恒大'],'单刀球':['单刀']}
entity_type_dict = {'武磊':'球员','郜林':'球员','前锋':'位置','上海上港':'球队','广州恒大':'球队','单刀球':'术语'}
ht.add_entities(entity_mention_dict,entity_type_dict)
print("\nSentence segmentation")
print(ht.seg(para,return_sent=True))    # return_sent=False时,则返回词语列表

上港 的 武磊 和 恒大 的 郜林 , 谁 是 中国 最好 的 前锋 ? 那 当然 是 武磊 武球王 了, 他 是 射手榜 第一 , 原来 是 弱点 的 单刀 也 有 了 进步

采用传统的分词工具很容易把“武球王”拆分为“武 球王”

词性标注,包括指定的特殊类型。

print("\nPOS tagging with entity types")
for word, flag in ht.posseg(para):
    print("%s:%s" % (word, flag),end = " ")

上港:球队 的:uj 武磊:球员 和:c 恒大:球队 的:uj 郜林:球员 ,:x 谁:r 是:v 中国:ns 最好:a 的:uj 前锋:位置 ?:x 那:r 当然:d 是:v 武磊:球员 武球王:球员 了:ul ,:x 他:r 是:v 射手榜:n 第一:m ,:x 原来:d 是:v 弱点:n 的:uj 单刀:术语 也:d 有:v 了:ul 进步:d

for span, entity in ht.entity_linking(para):
    print(span, entity)

[0, 2] ('上海上港', '#球队#') [3, 5] ('武磊', '#球员#') [6, 8] ('广州恒大', '#球队#') [9, 11] ('郜林', '#球员#') [19, 21] ('前锋', '#位置#') [26, 28] ('武磊', '#球员#') [28, 31] ('武磊', '#球员#') [47, 49] ('单刀球', '#术语#')

这里把“武球王”转化为了标准指称“武磊”,可以便于标准统一的统计工作。

分句:

print(ht.cut_sentences(para))

['上港的武磊和恒大的郜林,谁是中国最好的前锋?', '那当然是武磊武球王了,他是射手榜第一,原来是弱点的单刀也有了进步']

如果手头暂时没有可用的词典,不妨看看本库内置资源中的领域词典是否适合你的需要。

如果同一个名字有多个可能对应的实体("打球的李娜和唱歌的李娜不是一个人"),可以设置keep_all=True来保留多个候选,后面可以再采用别的策略消歧,见el_keep_all()

如果连接到的实体过多,其中有一些明显不合理,可以采用一些策略来过滤,这里给出了一个例子filter_el_with_rule()

本库能够也用一些基本策略来处理复杂的实体消歧任务(比如一词多义【"老师"是指"A老师"还是"B老师"?】、候选词重叠【xx市长/江yy?、xx市长/江yy?】)。 具体可见linking_strategy()

文本清洗

可以处理文本中的特殊字符,或者去掉文本中不希望出现的一些特殊格式。

包括:微博的@,表情符;网址;email;html代码中的 一类的特殊字符;网址内的%20一类的特殊字符;繁体字转简体字

例子如下:

print("各种清洗文本")
ht0 = HarvestText()
# 默认的设置可用于清洗微博文本
text1 = "回复@钱旭明QXM:[嘻嘻][嘻嘻] //@钱旭明QXM:杨大哥[good][good]"
print("清洗微博【@和表情符等】")
print("原:", text1)
print("清洗后:", ht0.clean_text(text1))
# URL的清理
text1 = "【#赵薇#:正筹备下一部电影 但不是青春片....http://t.cn/8FLopdQ"
print("清洗网址URL")
print("原:", text1)
print("清洗后:", ht0.clean_text(text1, remove_url=True))
# 清洗邮箱
text1 = "我的邮箱是abc@demo.com,欢迎联系"
print("清洗邮箱")
print("原:", text1)
print("清洗后:", ht0.clean_text(text1, email=True))
# 处理URL转义字符
text1 = "www.%E4%B8%AD%E6%96%87%20and%20space.com"
print("URL转正常字符")
print("原:", text1)
print("清洗后:", ht0.clean_text(text1, norm_url=True, remove_url=False))
text1 = "www.中文 and space.com"
print("正常字符转URL[含有中文和空格的request需要注意]")
print("原:", text1)
print("清洗后:", ht0.clean_text(text1, to_url=True, remove_url=False))
# 处理HTML转义字符
text1 = "<a c> ''"
print("HTML转正常字符")
print("原:", text1)
print("清洗后:", ht0.clean_text(text1, norm_html=True))
# 繁体字转简体
text1 = "心碎誰買單"
print("繁体字转简体")
print("原:", text1)
print("清洗后:", ht0.clean_text(text1, t2s=True))
各种清洗文本
清洗微博【@和表情符等】
原: 回复@钱旭明QXM:[嘻嘻][嘻嘻] //@钱旭明QXM:杨大哥[good][good]
清洗后: 杨大哥
清洗网址URL
原: 【#赵薇#:正筹备下一部电影 但不是青春片....http://t.cn/8FLopdQ
清洗后: 【#赵薇#:正筹备下一部电影 但不是青春片....
清洗邮箱
原: 我的邮箱是abc@demo.com,欢迎联系
清洗后: 我的邮箱是,欢迎联系
URL转正常字符
原: www.%E4%B8%AD%E6%96%87%20and%20space.com
清洗后: www.中文 and space.com
正常字符转URL[含有中文和空格的request需要注意]
原: www.中文 and space.com
清洗后: www.%E4%B8%AD%E6%96%87%20and%20space.com
HTML转正常字符
原: <a c> ''
清洗后: <a c> ''
繁体字转简体
原: 心碎誰買單
清洗后: 心碎谁买单

命名实体识别

找到一句句子中的人名,地名,机构名等命名实体。使用了 pyhanLP 的接口实现。

ht0 = HarvestText()
sent = "上海上港足球队的武磊是中国最好的前锋。"
print(ht0.named_entity_recognition(sent))
{'上海上港足球队': '机构名', '武磊': '人名', '中国': '地名'}

依存句法分析

分析语句中各个词语(包括链接到的实体)的主谓宾语修饰等语法关系,并以此提取可能的事件三元组。使用了 pyhanLP 的接口实现。

ht0 = HarvestText()
para = "上港的武磊武球王是中国最好的前锋。"
entity_mention_dict = {'武磊': ['武磊', '武球王'], "上海上港":["上港"]}
entity_type_dict = {'武磊': '球员', "上海上港":"球队"}
ht0.add_entities(entity_mention_dict, entity_type_dict)
for arc in ht0.dependency_parse(para):
    print(arc)
print(ht0.triple_extraction(para))
[0, '上港', '球队', '定中关系', 3]
[1, '的', 'u', '右附加关系', 0]
[2, '武磊', '球员', '定中关系', 3]
[3, '武球王', '球员', '主谓关系', 4]
[4, '是', 'v', '核心关系', -1]
[5, '中国', 'ns', '定中关系', 8]
[6, '最好', 'd', '定中关系', 8]
[7, '的', 'u', '右附加关系', 6]
[8, '前锋', 'n', '动宾关系', 4]
[9, '。', 'w', '标点符号', 4]
print(ht0.triple_extraction(para))
[['上港武磊武球王', '是', '中国最好前锋']]

字符拼音纠错

在V0.7版修改,使用tolerance支持拼音相同的检查

把语句中有可能是已知实体的错误拼写(误差一个字符或拼音)的词语链接到对应实体。

def entity_error_check():
    ht0 = HarvestText()
    typed_words = {"人名":["武磊"]}
    ht0.add_typed_words(typed_words)
    sent0 = "武磊和吴磊拼音相同"
    print(sent0)
    print(ht0.entity_linking(sent0, pinyin_tolerance=0))
    sent1 = "武磊和吴力只差一个拼音"
    print(sent1)
    print(ht0.entity_linking(sent1, pinyin_tolerance=1))
    sent2 = "武磊和吴磊只差一个字"
    print(sent2)
    print(ht0.entity_linking(sent2, char_tolerance=1))
    sent3 = "吴磊和吴力都可能是武磊的代称"
    print(sent3)
    print(ht0.get_linking_mention_candidates(sent3, pinyin_tolerance=1, char_tolerance=1))
武磊和吴磊拼音相同
[([0, 2], ('武磊', '#人名#')), [(3, 5), ('武磊', '#人名#')]]
武磊和吴力只差一个拼音
[([0, 2], ('武磊', '#人名#')), [(3, 5), ('武磊', '#人名#')]]
武磊和吴磊只差一个字
[([0, 2], ('武磊', '#人名#')), [(3, 5), ('武磊', '#人名#')]]
吴磊和吴力都可能是武磊的代称
('吴磊和吴力都可能是武磊的代称', defaultdict(<class 'list'>, {(0, 2): {'武磊'}, (3, 5): {'武磊'}}))

情感分析

本库采用情感词典方法进行情感分析,通过提供少量标准的褒贬义词语(“种子词”),从语料中自动学习其他词语的情感倾向,形成情感词典。对句中情感词的加总平均则用于判断句子的情感倾向:

print("\nsentiment dictionary")
sents = ["武磊威武,中超第一射手!",
      "武磊强,中超最第一本土球员!",
      "郜林不行,只会抱怨的球员注定上限了",
      "郜林看来不行,已经到上限了"]
sent_dict = ht.build_sent_dict(sents,min_times=1,pos_seeds=["第一"],neg_seeds=["不行"])
print("%s:%f" % ("威武",sent_dict["威武"]))
print("%s:%f" % ("球员",sent_dict["球员"]))
print("%s:%f" % ("上限",sent_dict["上限"]))

sentiment dictionary 威武:1.000000 球员:0.000000 上限:-1.000000

print("\nsentence sentiment")
sent = "武球王威武,中超最强球员!"
print("%f:%s" % (ht.analyse_sent(sent),sent))

0.600000:武球王威武,中超最强球员!

如果没想好选择哪些词语作为“种子词”,本库中也内置了一个通用情感词典内置资源,在不指定情感词时作为默认的选择,也可以根据需要从中挑选。

默认使用的SO-PMI算法对于情感值没有上下界约束,如果需要限制在[0,1]或者[-1,1]这样的区间的话,可以调整scale参数,例子如下:

print("\nsentiment dictionary using default seed words")
docs = ["张市筹设兴华实业公司外区资本家踊跃投资晋察冀边区兴华实业公司,自筹备成立以来,解放区内外企业界人士及一般商民,均踊跃认股投资",
        "打倒万恶的资本家",
    "该公司原定资本总额为二十五万万元,现已由各界分认达二十万万元,所属各厂、各公司亦募得股金一万万余元",
    "连日来解放区以外各工商人士,投函向该公司询问经营性质与范围以及股东权限等问题者甚多,络绎抵此的许多资本家,于参观该公司所属各厂经营状况后,对民主政府扶助与奖励私营企业发展的政策,均极表赞同,有些资本家因款项未能即刻汇来,多向筹备处预认投资的额数。由平津来张的林明棋先生,一次即以现款入股六十余万元"
   ]
# scale: 将所有词语的情感值范围调整到[-1,1]
# 省略pos_seeds, neg_seeds,将采用默认的情感词典 get_qh_sent_dict()
print("scale=\"0-1\", 按照最大为1,最小为0进行线性伸缩,0.5未必是中性")
sent_dict = ht.build_sent_dict(docs,min_times=1,scale="0-1")
print("%s:%f" % ("赞同",sent_dict["赞同"]))
print("%s:%f" % ("二十万",sent_dict["二十万"]))
print("%s:%f" % ("万恶",sent_dict["万恶"]))
print("%f:%s" % (ht.analyse_sent(docs[0]), docs[0]))
print("%f:%s" % (ht.analyse_sent(docs[1]), docs[1]))

print("scale=\"+-1\", 在正负区间内分别伸缩,保留0作为中性的语义")
sent_dict = ht.build_sent_dict(docs,min_times=1,scale="+-1")
print("%s:%f" % ("赞同",sent_dict["赞同"]))
print("%s:%f" % ("二十万",sent_dict["二十万"]))
print("%s:%f" % ("万恶",sent_dict["万恶"]))
print("%f:%s" % (ht.analyse_sent(docs[0]), docs[0]))
print("%f:%s" % (ht.analyse_sent(docs[1]), docs[1]))
sentiment dictionary using default seed words
scale="0-1", 按照最大为1,最小为0进行线性伸缩,0.5未必是中性
赞同:1.000000
二十万:0.153846
万恶:0.000000
0.449412:张市筹设兴华实业公司外区资本家踊跃投资晋察冀边区兴华实业公司,自筹备成立以来,解放区内外企业界人士及一般商民,均踊跃认股投资
0.364910:打倒万恶的资本家
scale="+-1", 在正负区间内分别伸缩,保留0作为中性的语义
赞同:1.000000
二十万:0.000000
万恶:-1.000000
0.349305:张市筹设兴华实业公司外区资本家踊跃投资晋察冀边区兴华实业公司,自筹备成立以来,解放区内外企业界人士及一般商民,均踊跃认股投资
-0.159652:打倒万恶的资本家

信息检索

可以从文档列表中查找出包含对应实体(及其别称)的文档,以及统计包含某实体的文档数。使用倒排索引的数据结构完成快速检索。

docs = ["武磊威武,中超第一射手!",
        "郜林看来不行,已经到上限了。",
        "武球王威武,中超最强前锋!",
        "武磊和郜林,谁是中国最好的前锋?"]
inv_index = ht.build_index(docs)
print(ht.get_entity_counts(docs, inv_index))  # 获得文档中所有实体的出现次数
# {'武磊': 3, '郜林': 2, '前锋': 2}

print(ht.search_entity("武磊", docs, inv_index))  # 单实体查找
# ['武磊威武,中超第一射手!', '武球王威武,中超最强前锋!', '武磊和郜林,谁是中国最好的前锋?']

print(ht.search_entity("武磊 郜林", docs, inv_index))  # 多实体共现
# ['武磊和郜林,谁是中国最好的前锋?']

# 谁是最被人们热议的前锋?用这里的接口可以很简便地回答这个问题
subdocs = ht.search_entity("#球员# 前锋", docs, inv_index)
print(subdocs)  # 实体、实体类型混合查找
# ['武球王威武,中超最强前锋!', '武磊和郜林,谁是中国最好的前锋?']
inv_index2 = ht.build_index(subdocs)
print(ht.get_entity_counts(subdocs, inv_index2, used_type=["球员"]))  # 可以限定类型
# {'武磊': 2, '郜林': 1}

关系网络

(使用networkx实现) 利用词共现关系,建立其实体间图结构的网络关系(返回networkx.Graph类型)。可以用来建立人物之间的社交网络等。

# 在现有实体库的基础上随时新增,比如从新词发现中得到的漏网之鱼
ht.add_new_entity("颜骏凌", "颜骏凌", "球员")
docs = ["武磊和颜骏凌是队友",
        "武磊和郜林都是国内顶尖前锋"]
G = ht.build_entity_graph(docs)
print(dict(G.edges.items()))
G = ht.build_entity_graph(docs, used_types=["球员"])
print(dict(G.edges.items()))

获得以一个词语为中心的词语网络,下面以三国第一章为例,探索主人公刘备的遭遇(下为主要代码,例子见build_word_ego_graph())。

entity_mention_dict, entity_type_dict = get_sanguo_entity_dict()
ht0.add_entities(entity_mention_dict, entity_type_dict)
sanguo1 = get_sanguo()[0]
stopwords = get_baidu_stopwords()
docs = ht0.cut_sentences(sanguo1)
G = ht0.build_word_ego_graph(docs,"刘备",min_freq=3,other_min_freq=2,stopwords=stopwords)

word_ego_net

刘关张之情谊,刘备投奔的靠山,以及刘备讨贼之经历尽在于此。

文本摘要

(使用networkx实现) 使用Textrank算法,得到从文档集合中抽取代表句作为摘要信息,可以设置惩罚重复的句子,也可以设置字数限制(maxlen参数):

print("\nText summarization")
docs = ["武磊威武,中超第一射手!",
        "郜林看来不行,已经到上限了。",
        "武球王威武,中超最强前锋!",
        "武磊和郜林,谁是中国最好的前锋?"]
for doc in ht.get_summary(docs, topK=2):
    print(doc)
print("\nText summarization(避免重复)")
for doc in ht.get_summary(docs, topK=3, avoid_repeat=True):
    print(doc)
Text summarization
武球王威武,中超最强前锋!
武磊威武,中超第一射手!

Text summarization(避免重复)
武球王威武,中超最强前锋!
郜林看来不行,已经到上限了。
武磊和郜林,谁是中国最好的前锋?

关键词抽取

目前提供包括textrank和HarvestText封装jieba并配置好参数和停用词的jieba_tfidf(默认)两种算法。

示例(完整见example):

# text为林俊杰《关键词》歌词
print("《关键词》里的关键词")
kwds = ht.extract_keywords(text, 5, method="jieba_tfidf")
print("jieba_tfidf", kwds)
kwds = ht.extract_keywords(text, 5, method="textrank")
print("textrank", kwds)
《关键词》里的关键词
jieba_tfidf ['自私', '慷慨', '落叶', '消逝', '故事']
textrank ['自私', '落叶', '慷慨', '故事', '位置']

CSL.ipynb提供了不同算法,以及本库的实现与textrank4zh的在CSL数据集上的比较。由于仅有一个数据集且数据集对于以上算法都很不友好,表现仅供参考。

算法 P@5 R@5 F@5
textrank4zh 0.0836 0.1174 0.0977
ht_textrank 0.0955 0.1342 0.1116
ht_jieba_tfidf 0.1035 0.1453 0.1209

内置资源

现在本

Core symbols most depended-on inside this repo

entity_linking
called by 21
harvesttext/harvesttext.py
seg
called by 17
harvesttext/harvesttext.py
posseg
called by 14
harvesttext/harvesttext.py
add_entities
called by 12
harvesttext/harvesttext.py
clear
called by 10
harvesttext/harvesttext.py
get_baidu_stopwords
called by 9
harvesttext/resources.py
cut_sentences
called by 8
harvesttext/harvesttext.py
search_entity
called by 7
harvesttext/ent_retrieve.py

Shape

Method 93
Function 81
Class 14

Languages

Python100%

Modules by API surface

harvesttext/harvesttext.py36 symbols
examples/basics.py27 symbols
tests/test_functionality.py18 symbols
harvesttext/algorithms/word_discoverer.py14 symbols
examples/naiveKGQA.py14 symbols
harvesttext/algorithms/sent_dict.py10 symbols
harvesttext/algorithms/entity_discoverer.py9 symbols
harvesttext/resources.py8 symbols
harvesttext/download_utils.py7 symbols
harvesttext/algorithms/match_patterns.py7 symbols
harvesttext/word_discover.py6 symbols
harvesttext/parsing.py6 symbols

For agents

$ claude mcp add HarvestText \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact

Ask about this repo answers extend the page