一、任务描述
数据集是github上某大神整理出来的全八季任务信息,包括姓名、家族、杀了谁、被谁杀了等等。本文做的知识图谱仅包含所有人物及其被杀关系和家族关系。
数据集链接:https://github.com/jeffreylancaster/game-of-thrones/blob/master/data/characters.json
二、neo4j的安装和部署
参考:https://www.cnblogs.com/ljhdo/p/5521577.html
1.安装Java JRE
下载地址:https://www.oracle.com/technetwork/java/javase/downloads/index.html
配置Java环境变量。
第一步,新建JAVA_HOME变量,变量值填写jdk的安装目录,默认的安装目录是:C:\Program Files\Java\jre1.8.0_211
第二步,编辑Path变量,在Path变量值的最后输入:%JAVA_HOME%\bin;%JAVA_HOME%\jre\bin;
检查配置是否成功,运行cmd,输入java -version,如果显示java的版本信息,说明Java的安装和配置成功。
2.安装Neo4j
下载地址:https://neo4j.com/download-center/
解压到主目录,“D:\Program Files\neo4j-community-3.2.”。
Neo4j应用程序有如下主要的目录结构:
- bin目录:用于存储Neo4j的可执行程序;
- conf目录:用于控制Neo4j启动的配置文件;
- data目录:用于存储核心数据库文件;
- plugins目录:用于存储Neo4j的插件;
配置Neo4j环境变量:创建主目录环境变量NEO4J_HOME,并把主目录设置为变量值。
3.启动Neo4j
以管理员身份启动命令行,切换到D:\Program Files\neo4j-community-3.2.\bin,输入以下命令,通过控制台启用neo4j程序:
neo4j.bat console
如果看到以下消息,说明neo4j已经开始运行:
4.Neo4j浏览器
通过命令行启动neo4j之后,访问 “http://localhost:7474/”
默认的host是bolt://localhost:7687,默认的用户是neo4j,默认的密码是:neo4j,第一次成功connect到Neo4j服务器之后,需要重置密码。
5.在Neo4j浏览器中创建节点和关系
CREATE (n:Person { name: 'Andres', title: 'Developer' }) return n;
CREATE (n:Person { name: 'Vic', title: 'Developer' }) return n;
match(n:Person{name:"Vic"}),(m:Person{name:"Andres"}) create (n)-[r:Friend]->(m) return r;
match(n:Person{name:"Vic"}),(m:Person{name:"Andres"}) create (n)<-[r:Friend]-(m) return r;
三、数据处理
从数据集中抽取需要的信息生成节点和关系csv文件。
原始数据集如下图:
只需要其中的characterName、houseName和killedBy信息,同时去除没有人物图片和重复的小角色,建立一个notuse.txt
import json
import pandas as pd
with open('./characters.json', 'r') as f:
data = json.load(f)
with open('./notuse.txt', 'r') as f:
notuse = []
for name in f.readlines():
name = name.strip()
notuse.append(name)
characters = []
character2index = {}
index2character = {}
house2index = {}
index2house = {}
character = {'index:ID':[],
'name':[],
':LABEL':[]}
house = {'index:ID':[],
'name':[],
':LABEL':[]}
kill = {':START_ID':[],
':END_ID':[],
'relation':[],
':TYPE':[]}
belong = {':START_ID':[],
':END_ID':[],
'relation':[],
':TYPE':[]}
index_character = 1
index_house = 10001
for dic in data['characters']:
if 'characterImageThumb' in dic.keys() and dic['characterName'] not in notuse:
characters.append(dic)
# 构建character节点
name2index[dic['characterName']] = index_character
index2name[index_character] = dic['characterName']
character['index:ID'].append(index_character)
character['name'].append(dic['characterName'])
character[':LABEL'].append('character')
index_character += 1
# 构建house节点
if 'houseName' in dic:
if type(dic['houseName']) == str:
if dic['houseName'] not in house['name']:
house2index[dic['houseName']] = index_house
index2house[index_house] = dic['houseName']
house['index:ID'].append(index_house)
house['name'].append(dic['houseName'])
house[':LABEL'].append('house')
index_house += 1
elif type(dic['houseName']) == list:
for hname in dic['houseName']:
if hname not in house['name']:
house2index[hname] = index_house
index2house[index_house] = hname
house['index:ID'].append(index_house)
house['name'].append(hname)
house[':LABEL'].append('house')
index_house += 1
for person in characters:
# 构建killedBy关系
if 'killedBy' in person.keys():
for killer in person['killedBy']:
if killer in name2index.keys():
kill[':START_ID'].append(name2index[person['characterName']])
kill[':END_ID'].append(name2index[killer])
kill['relation'].append('killedBy')
kill[':TYPE'].append('killedBy')
# 构建belongTo关系
if 'houseName' in person.keys():
if type(person['houseName']) == str:
belong[':START_ID'].append(name2index[person['characterName']])
belong[':END_ID'].append(house2index[person['houseName']])
belong['relation'].append('belongTo')
belong[':TYPE'].append('belongTo')
elif type(person['houseName']) == list:
for h in person['houseName']:
belong[':START_ID'].append(name2index[person['characterName']])
belong[':END_ID'].append(house2index[h])
belong['relation'].append('belongTo')
belong[':TYPE'].append('belongTo')
df_character = pd.DataFrame(character)
df_house = pd.DataFrame(house)
df_kill = pd.DataFrame(kill)
df_belong = pd.DataFrame(belong)
df_character.to_csv('./character.csv', index=False)
df_house.to_csv('./house.csv', index=False)
df_kill.to_csv('./kill.csv', index=False)
df_belong.to_csv('./belong.csv', index=False)
构建节点和关系csv文件时,注意以下几点:
1.所有的节点文件,第一列都要为“index:ID”,最后一列都要为":LABEL" , 中间所有列即为这个实体的属性。注意实体属性最好不要用中文,label即为这个实体的对应标签。
人物节点文件character.csv:
家族节点文件house.csv:
2.所有的关系文件,第一列都要为“:START_ID”,第二列都要为":END_ID",第三列要为"relation",第四列要为":TYPE" , start_id对应一个节点的index_id,end_id对应另一个节点的index_id,relation即为两者的关系,type即为标签,一般type和relation内容相同。
击杀关系文件kill.csv:
家族关系文件belong.csv:
3.不管是实体还是关系文件里的index_id,可以在一开始设一个比数据规模大出两个数量级的初始值,比如本文的家族id都是10000+i,因为主键设的太小容易造成不同文件的主键混淆。
参考:https://blog.csdn.net/shr903988854/article/details/83145088
四、导入Neo4j数据库
节点路径和关系路径可以根据自己需要指定。文件路径的根目录默认为neo4j/bin。
另外,在执行此语句前要确保没有got.db这个数据库,并且conf文件中注释这句dbms.active_database=got.db(如果存在的话),不然会报数据库存在的错误。
导入成功后,再在conf文件中添加语句dbms.active_database=got.db或取消注释。
在浏览器中查看人物及其关系:
用cypher语句可以对数据库进行增删改查操作
教程:http://neo4j.com.cn/public/cypher/default.html
熟悉了知识存储和检索操作,接下来看一下知识推理和知识融合,希望在2019DeeCamp上能做出完整的知识图谱吧。