!pip install hanlp -U

"""
Explanation: <h2 align="center">点击下列图标在线运行HanLP</h2>
<div align="center">
    <a href="https://colab.research.google.com/github/hankcs/HanLP/blob/doc-zh/plugins/hanlp_demo/hanlp_demo/zh/con_stl.ipynb" target="_blank"><img src="https://colab.research.google.com/assets/colab-badge.svg" alt="Open In Colab"/></a>
    <a href="https://mybinder.org/v2/gh/hankcs/HanLP/doc-zh?filepath=plugins%2Fhanlp_demo%2Fhanlp_demo%2Fzh%2Fcon_stl.ipynb" target="_blank"><img src="https://mybinder.org/badge_logo.svg" alt="Open In Binder"/></a>
</div>

安装
无论是Windows、Linux还是macOS，HanLP的安装只需一句话搞定：
End of explanation
"""


import hanlp
hanlp.pretrained.constituency.ALL # 语种见名称最后一个字段或相应语料库

"""
Explanation: 加载模型
HanLP的工作流程是先加载模型，模型的标示符存储在hanlp.pretrained这个包中，按照NLP任务归类。
End of explanation
"""


con = hanlp.load('CTB9_CON_FULL_TAG_ELECTRA_SMALL')

"""
Explanation: 调用hanlp.load进行加载，模型会自动下载到本地缓存。
End of explanation
"""


trees = con([["2021年", "HanLPv2.1", "为", "生产", "环境", "带来", "次", "世代", "最", "先进", "的", "多", "语种", "NLP", "技术", "。"], ["阿婆主", "来到", "北京", "立方庭", "参观", "自然", "语义", "科技", "公司", "。"]], tasks='con')

"""
Explanation: 短语句法分析
输入为已分词的一个或多个句子：
End of explanation
"""


print(trees)

"""
Explanation: 返回值为一个Tree的数组:
End of explanation
"""


print(trees[0])

"""
Explanation: 转换为bracketed格式：
End of explanation
"""


pos = hanlp.load(hanlp.pretrained.pos.CTB9_POS_ELECTRA_SMALL)

"""
Explanation: 组装流水线
短语成分树的第一层non-terminal一般是词性标签，所以经常与词性标注一起使用。为此，先加载一个词性标注器：
End of explanation
"""


from hanlp_common.document import Document
def merge_pos_into_con(doc:Document):
    flat = isinstance(doc['pos'][0], str)
    if flat:
        doc = Document((k, [v]) for k, v in doc.items())
    for tree, tags in zip(doc['con'], doc['pos']):
        offset = 0
        for subtree in tree.subtrees(lambda t: t.height() == 2):
            tag = subtree.label()
            if tag == '_':
                subtree.set_label(tags[offset])
            offset += 1
    if flat:
        doc = doc.squeeze()
    return doc

"""
Explanation: 然后创建一个函数将词性标签和句法树组装起来:
End of explanation
"""


nlp = hanlp.pipeline() \
    .append(pos, input_key='tok', output_key='pos') \
    .append(con, input_key='tok', output_key='con') \
    .append(merge_pos_into_con, input_key='*')

"""
Explanation: 之后就可以用一个流水线将三者组装起来了：
End of explanation
"""


print(nlp)

"""
Explanation: 该流水线的结构如下：
End of explanation
"""


doc = nlp(tok=["2021年", "HanLPv2.1", "带来", "最", "先进", "的", "多", "语种", "NLP", "技术", "。"])
print(doc)

"""
Explanation: 传入一个已分词的句子试试：
End of explanation
"""


doc.pretty_print()

"""
Explanation: 流水线的输出也是一个Document，所以支持可视化：
End of explanation
"""


tok = hanlp.load(hanlp.pretrained.tok.COARSE_ELECTRA_SMALL_ZH)

"""
Explanation: 如果要分析原始文本的话，分词是第一步，所以先加载一个分词器：
End of explanation
"""


nlp.insert(0, tok, output_key='tok')

"""
Explanation: 然后将分词器插入到流水线的第一级：
End of explanation
"""


print(nlp('2021年HanLPv2.1带来最先进的多语种NLP技术。')['con'])

"""
Explanation: 然后就可以直接分析原始文本了：
End of explanation
"""


tree = doc['con'] # tree数组的话则需要doc['con'][0]
print(tree)

"""
Explanation: 你明白吗？HanLP是为聪明人设计的，只要你足够聪明，你就可以优雅地实现各种功能。
操作短语树的技巧
短语结构树的类型为phrasetree.tree.Tree，提供了许多接口，此处列举其中一些常用的接口。
End of explanation
"""


for subtree in tree.subtrees(lambda t: t.height() == 4):
    print(f'子树：{subtree}\t标签：{subtree.label()}\t短语：{subtree.leaves()}')

"""
Explanation: 按高度枚举子树
End of explanation
"""


for subtree in tree.subtrees(lambda t: t.label() == 'NP'):
    print(subtree)

"""
Explanation: 按标签枚举子树
End of explanation
"""


print(f'父节点{subtree}的子节点有：')
for child in subtree:
    print(child)

"""
Explanation: 遍历子节点
End of explanation
"""


