基于医疗知识图谱的问答系统

一、项目主体结构
该项目分为知识图谱的构建、基于知识图谱的问答两部分,build_medicalgraph.py构建图谱、chatbot_graph.py启动问题系统,项目中的文件层次结构如下:

├── E:\QASystemOnMedicalKG
├── data
├── medical.json
├── dict
├── check.txt
├── deny.txt
├── department.txt
├── disease.txt
├── drug.txt
├── food.txt
├── producer.txt
├── symptom.txt
├── prepare_data
├── build_data.py
├── data_spider.py
├── disease.txt
├── first_name.txt
├── first_name_spider.py
├── max_cut.py
├── answer_search.py
├── build_medicalgraph.py
├── chatbot_graph.py
├── question_classifier.py
├── question_parser.py
├── README.md

二、知识图谱构建
(一)爬取以疾病为核心的医疗数据,数据量大,普通个人计算机爬取数据程序运行时间需耗时一天,需将爬取数据导入非关系型数据库mongodb,见脚本data_spider.py。下图是爬取的原始数据在mongodb中的存储形式。

(二)对爬取的数据进行清洗,整理成“节点:属性”的可直接导入图形数据库neo4j的字典形式,并将清洗后的数据导入mongodb,见脚本build_data.py。(因数据清洗需要的first_name.txt文件遗失,笔者通过分析build_data.py代码,在原项目爬虫程序部分进行适当增删,编写了爬取first_name.txt的first_name_spider.py脚本。读者需要,可拷贝如下代码或转链接:https://pan.baidu.com/s/1LNMyffgl4Qic1EryFDimkg下载,提取码:37ul)。

#!/usr/bin/python3
# -*- coding:utf-8 -*-

“””

@Time : 2020/1/31 21:25
@Software: PyCharm
@FileName: first_name_spider.py
“””
import urllib.request
import urllib.parse
from lxml import etree

”’爬取寻医问药网医生姓名”’
class CrimeSpider:
def __init__(self):
pass

”’根据url,请求html”’
def get_html(self, url):
headers = {‘User-Agent’: ‘Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) ‘
‘Chrome/51.0.2704.63 Safari/537.36’}
req = urllib.request.Request(url=url, headers=headers)
res = urllib.request.urlopen(req)
html = res.read().decode(‘gbk’)
return html

”’url解析”’
def url_parser(self, content):
selector = etree.HTML(content)
urls = [‘http://www.anliguan.com’ + i for i in selector.xpath(‘//h2[@class=”item-title”]/a/@href’)]
return urls

”’测试”’
def spider_main(self):
namesList = []
for page in range(1, 11000):
try:
symptom_url = ‘http://jib.xywy.com/il_sii/symptom/%s.htm’%page
names = self.name_spider(symptom_url)
namesList.extend(names)
print(page, symptom_url)
except Exception as e:
print(e, page)

self.save_names(namesList)
return

def save_names(self,namesList):
with open(‘first_name.txt’,’w’,encoding=’utf-8′) as f:
for name in namesList:
f.write(name + “\n”)

”’姓名信息解析”’
def name_spider(self, url):
html = self.get_html(url)
selector = etree.HTML(html)
names = selector.xpath(‘//span[@class=”fr replay-docter”]//a[@class=”gre”]/text()’)
return names
if __name__ == ‘__main__’:
handler = CrimeSpider()
handler.spider_main()

(三)根据字典形式的数据创建结点,以疾病为中心定义关系形成三元组表示的知识,将结点和关系导入neo4j数据库形成知识图谱,见脚本build_medicalgraph.py。下图是根据清洗后的数据生成的知识图谱。
三、问题系统构成
问题系统是该项目的核心部分,主要由问句分类、问句解析、答案搜索三部分构成。
(一)问句分类
问句分类原项目采用了“两步走”的方式,第一步是用AC自动机算法识别问题中的关键字,根据事先构建的“实体:类型”大型字典确认关键字的类型。第二步是基于规则的方法,依据经验构建数种疑问句关键词字典,再根据这些关键字是否存在于问句来确定问句的类型。实际上,类型的确定就是一个多分类的问题。问句分类是问答部分的核心。
(二)问句解析
问句解析的实质是根据问句类型,选择适当的neo4j的match匹配语句。
(三)答案搜索
访问neo4j数据库,执行问句解析得到了match语句,并将执行结果转化为用户可以接受的形式。