使用Neo4j+InteractiveGraph实现豆瓣电影知识图谱可视化
本文介绍了基于豆瓣电影数据构建的知识图谱项目,并展示了其可视化与交互分析的过程。项目使用Neo4j作为图数据库,并结合InteractiveGraph进行图存储与可视化展示。
主要内容:
知识图谱构建:
- 构建了包含电影(Movie)、演员(Person)与导演(Director)三种节点的数据模型。
- 数据来源为openKG中的douban-movie-kg dataset。
- 使用Pandas读取并清洗JSON格式数据,提取人物信息并生成CSV文件作为边数据。
- 对人员信息去重并导出为节点及关系文件。
- 在Neo4j中导入三类关系:演员-饰演-电影、导演-执导-电影及编剧-撰写-电影。
导入与配置:- 使用Cypher语言将CSV文件导出至Neo4j数据库。
- 配置了索引以加快关系查找速度。
- 设置了前后端访问接口(如Tomcat + Webapps + InteractiveGraph)完成知识图谱的展示与分析功能。
可视化工具:- 使用InteractiveGraph-neo4j实现全局视图预览功能(如graphserver)。
- 提供了图导航器(GraphNavigator)、图浏览器(GraphExplorer)及关系查找器(RelationFinder)等交互界面。
- 配置了语言设置并连接到服务端接口以实现多终端访问。
本文通过以上方法完成了从数据采集到知识图谱构建再到可视化的完整流程,并展示了系统的扩展性和灵活性。
0.介绍
本文利用豆瓣电影数据开发了一套电影知识图谱,该系统涵盖了电影、演员、导演等多个维度的信息以及它们之间的关联关系,并采用InteractiveGraph技术实现了可视化的功能
- 数据量充足,该系统构建了一个包含约27,000个节点和50,000条关系的复杂知识图谱。
- 基于Neo4j的图数据库技术架构实现数据存储与管理。
- 支持大规模图景的整体展示与预览功能。
- 提供节点间关联关系的识别与分析功能。
- 允许用户按需展开查看各节点的具体信息及其关联网络。
所用到的程序包括:
- Tomcat Version 8.5
- Neo4j Open Source Version 3.5.12
- Interactive Graph v0.3.2 (项目地址:https://github.com/grapheco/InteractiveGraph) 欢迎star
- Interactive Graph with Neo4j v0.0.3 (项目地址:https://github.com/grapheco/InteractiveGraph-neo4j)
1.数据处理
该数据源自OpenKG平台(http://www.openkg.cn/dataset/douban-movie-kg),基于豆瓣电影的数据集。以下为示例数据,包含片名、图片预览图、分类以及语言信息基础资料等核心团队成员的信息。


豆瓣电影
{
"id": 1292052,
"title": "肖申克的救赎",
"url": "http://movie.douban.com/subject/1292052/",
"cover": "http://img3.douban.com/view/movie_poster_cover/lpst/public/p480747492.jpg",
"rate": 9.6,
"director": ["弗兰克·德拉邦特"],
"composer": ["弗兰克·德拉邦特", "斯蒂芬·金"],
"actor": ["蒂姆·罗宾斯", "摩根·弗里曼", "鲍勃·冈顿", "威廉姆·赛德勒", "克兰西·布朗", "吉尔·贝罗斯", "马克·罗斯顿", "詹姆斯·惠特摩", "杰弗里·德曼", "拉里·布兰登伯格", "尼尔·吉恩托利", "布赖恩·利比", "大卫·普罗瓦尔", "约瑟夫·劳格诺", "祖德·塞克利拉"],
"category": ["剧情", "犯罪"],
"district": ["United States of America_美国"],
"language": ["英语"],
"showtime": 1994.0,
"length": 142.0,
"othername": ["月黑高飞(港)", "刺激1995(台)", "地狱诺言", "铁窗岁月", "消香克的救赎"]
}
该数据集以JSON格式存在,并且在导入Neo4j之前还需进行相应的处理;随后,请通过使用Pandas库的方式将数据导入至系统中:
import pandas as pd
import numpy as np
# 读入数据集
data = pd.read_json('data/dbmovies.json', dtype=object)
在构建该图谱的过程中(由于)最终构建的图谱包含了电影这一类节点以及人这一类节点(因此),需要从电影信息中提取出人物相关信息。(观察)通过分析数据集可知(发现),这些人物信息主要集中在演员、导演和编剧这三个字段中。(进而)需要将这三类信息转换为边的形式,并整合生成相应的人员数据(合并出人员节点数据)。
举例而言,在处理演员数据时,请先将actor表中的演员集合构建一个包含电影ID和演员姓名两列的新DataFrame结构,并将其保存为CSV文件以便后续处理作为边数据使用。选择CSV格式便于Neo4j高效处理导入这些关系数据。
在获得了边数据后,在此基础上将这三类人物首先提取到一列,并对提取的数据进行去重处理。在此过程中,默认地假设演员之间的同名情况属于同一身份。类似的,在整合数据后也会将其转换为CSV格式作为人员节点数据。
person = pd.DataFrame()
labels = ['actor', 'director', 'composer']
for label in labels:
df = data[['id', label]]
df = df.dropna(axis=0, how='any')
df = pd.DataFrame({'id': df['id'].repeat(df[label].str.len()),
label: np.concatenate(df[label].values)})
person = pd.concat([person, df[label]], axis=0)
df.to_csv('data/'+label+'.csv', index=False)
person.drop_duplicates(inplace=True, ignore_index=True)
person.to_csv('data/person.csv', index=False)
在完成人员信息的处理后,则有必要对电影信息进行相应的处理。具体而言,在这一过程中,主要是将类似数组的这类非字符串数据进行转换工作,并将其转化为符合需求的字符串形式。同时,在完成上述操作的同时,则需要将这些数据进一步导出为包含电影节点的CSV文件形式
data.drop(labels, axis=1, inplace=True)
list_labels = ['category', 'district', 'language', 'othername']
for list_label in list_labels:
data[list_label] = data[list_label].apply(lambda x: '、'.join(x) if x!=None else x)
data.to_csv('data/movie.csv', index=False)
2.导入数据
启动数据导入流程,在Neo4j环境中进行操作。首先将所有生成的CSV文件复制至Neo4j安装目录指定的import子目录下,并确保系统已开启以便于后续操作。
采用Cypher语句导入电影节点数据信息时,请特别注意对评分字段、上映年份以及时长等数值属性进行预处理工作;如果不做特殊处理的话,默认情况下这些字段会被识别为字符串类型无法参与后续计算。
USING PERIODIC COMMIT 500
LOAD CSV WITH HEADERS FROM 'file:///movie.csv' AS line
CREATE (:Movie{
id: line.id,
name: line.title,
url: line.url,
image: line.cover,
rate: toFloat(line.rate),
category: line.category,
district: line.district,
language: line.language,
showtime: toInteger(line.showtime),
length: toInteger(line.length),
othername: line.othername
})
导入人物数据:
USING PERIODIC COMMIT 500
LOAD CSV FROM 'file:///person.csv' AS line
CREATE (:Person{name:line[0]})
在建立关系之前,在线构建数据库时必须对节点字段进行索引处理,在提升数据检索效率方面具有显著作用
CREATE INDEX ON :Movie(id)
CREATE INDEX ON :Movie(name)
CREATE INDEX ON :Person(name)
创建三种关系,分别是(人物)-[:饰演]->(电影),(人物)-[:导演]->(电影)和(人物)-[:编剧]->(电影)。
USING PERIODIC COMMIT 500
LOAD CSV WITH HEADERS FROM 'file:///actor.csv' AS line
MATCH (p:Person) where p.name = line.actor WITH p,line
MATCH (m:Movie) where m.id = line.id
MERGE (p)-[:play]->(m)
USING PERIODIC COMMIT 500
LOAD CSV WITH HEADERS FROM 'file:///director.csv' AS line
MATCH (p:Person) where p.name = line.director WITH p,line
MATCH (m:Movie) where m.id = line.id
MERGE (p)-[:direct]->(m)
USING PERIODIC COMMIT 500
LOAD CSV WITH HEADERS FROM 'file:///composer.csv' AS line
MATCH (p:Person) where p.name = line.composer WITH p,line
MATCH (m:Movie) where m.id = line.id
MERGE (p)-[:write]->(m)
这一步对人物进行了评分计算,在考虑其参与的所有作品(包括参演、编剧或导演)的情况下,将这些作品的平均分作为其综合评价依据。
match (p:Person)-[]-(m:Movie) with p,avg(m.rate)*10 as avg
set p.rate = round(avg)/10
3.配置可视化系统
本系统包含两个核心组件:InteractiveGraph和InteractiveGraph-neo4j。其中InteractiveGraph作为Web前端模块主要承担数据展示与交互操作;而InteractiveGraph-neo4j则作为后端管理模块处理数据存储与接口接入问题。
InteractiveGraph-neo4j安装与配置
下载与部署
首先通过GitHub获取最新版本InteractiveGraph-neo4j软件包:https://github.com/grapheco/InteractiveGraph-neo4j/releases
将该软件包成功下载完成后将其放置于Tomcat的webapps目录内 Tomcat系统会自动执行解压操作并创建graphserver文件夹(如果系统未自动解压建议重启Tomcat以恢复正常工作流程)。
修改配置文件
修改配置文件graphserver/WEB_INF/conf1.properties:
allowOrigin=*
backendType=neo4j-bolt
neo4j.boltUrl=bolt://localhost:7687
neo4j.boltUser=neo4j
neo4j.boltPassword=1
neo4j.regexpSearchFields=name
neo4j.strictSearchFields=label:name
neo4j.nodeCategories=Person:人物,Movie:电影
layout_on_startup=false
visNodeProperty.label==$prop.name
visNodeProperty.value==$prop.rate
visNodeProperty.image==$prop.image
visNodeProperty.x ==$prop.x
visNodeProperty.y ==$prop.y
visNodeProperty.info=<p align=center> #if($prop.image) <img width=150 src="${prop.image}"><br> #end <b>${prop.name}</b></p><p align=left><ul><li>评分:${node.rate}</li><li>类型:${node.category}</li><li>时长:${node.length}分钟</li><li>语言:${node.language}</li></ul></p>
其中:
- allowOrigin:是允许访问的域,默认允许所有,这里不需要修改;
- backendType:后端类型,本文使用的是neo4j因此也不需要修改;
- neo4j.boltUrl:Neo4j的地址;
- neo4j.boltUser:Neo4j用户名;
- neo4j.boltPassword:Neo4j密码;
- neo4j.regexpSearchFields:这一项是搜索时匹配的字段名,在这里指定为节点的
name字段; - neo4j.strictSearchFields:严格搜索的接受格式,这里设置为
节点label:name字段(如Person:周星驰); - neo4j. nodeCategories:这一项指定数据库中有哪些节点类型,本文中有人物和电影;
- layout_on_startup:是否自动布局。本文中数据有几万个节点和边,这个数量级的数据前端浏览器的计算力已经不足以每次都对数据在线布局。因此需要服务端使用布局算法离线计算节点位置,并记录在Neo4j中。由于本文的数据库中没有位置信息,因此这一项设置为
true。当本次预计算完成后,下一次启动服务端时可以设置成false避免再次计算; - visNodeProperty.label:前端可视化节点显示的名称对应的字段,这里设置为数据库中节点的
name字段; - visNodeProperty.value:前端可视化节点的值对应的字段。值的大小决定了前端显示的节点的实际大小。这里设置为
rate字段,这样在前端显示时,类似《肖申克的救赎》这样的高分节点就会显示的比较大,而《上海堡垒》这种烂片就会显示的比较小; - visNodeProperty.image:前端可视化节点的图片对应的字段,这里设置为数据库节点中的
image字段; - visNodeProperty.x:前端可视化节点的x坐标对应的字段,默认为数据库的
x字段,因为自动布局算法设定的就是这个字段所以这里不用更改,如果数据库本事有位置信息可以自行指定; - visNodeProperty.y: 同上;
- visNodeProperty.info:前端信息面板的展示代码。在本文中设定和对应效果如下:
<p align=center>
#if($prop.image)
<img width=150 src="${prop.image}"><br>
#end
<b>${prop.name}</b>
</p>
<p align=left>
<ul>
<li>评分:${node.rate}</li>
<li>类型:${node.category}</li>
<li>时长:${node.length}分钟</li>
<li>语言:${node.language}</li>
</ul>
</p>


信息面板效果
在配置完成之后,请先重启Tomcat服务。接着,请访问浏览器中的地址http://localhost:8080/graphserver/。若在页面上看到相应的提示信息,则表示服务端配置已成功完成。
InteractiveGraph安装与配置
下载与部署
首先从github下载最新的发行版:
https://github.com/grapheco/InteractiveGraph/releases
igraph.zip包含InteractiveGraph的js文件,可以结合项目README的流程自行使用。
本文直接下载了examples.zip中的示例内容,在其上做了适当修改。
首先在tomcat的webapps目录中新建igraph文件夹,并将examples.zip中的内容解压到这个文件夹中。
InteractiveGraph工具包括三个应用:
- GraphNavigator:图导航器,提供对整个图的全局视图可视化预览;
- GraphExplorer:图浏览器,通过对某个节点的展开操作,逐步浏览该节点和拓展节点的信息;
- RelationFinder:关系查找器,提供两个节点间的关系路径发现。
上述3个应用分别在example1.html,example2.html和example3.html。接下来需要修改其中的内容。
修改配置
打开example1.html,将js中app.loadGson修改为:
igraph.i18n.setLanguage("chs");
var app = new igraph.GraphNavigator(document.getElementById('graphArea'), 'LIGHT');
//修改了这下面↓,上面不要改
app.connect("http://localhost:8080/graphserver/connector-bolt");
这里的localhost:8080为graphserver的地址。
同理,对example2.html和example3.html也做上述修改。
igraph.i18n.setLanguage("chs");
var app = new igraph.GraphExplorer(document.getElementById('graphArea'));
//修改了这下面↓,上面不要改
app.connect("http://localhost:8080/graphserver/connector-bolt");
igraph.i18n.setLanguage("chs");
var app = new igraph.RelFinder(document.getElementById('graphArea'));
//修改了这下面↓,上面不要改
app.connect("http://localhost:8080/graphserver/connector-bolt");
4.可视化展示
图导航器
浏览器打开http://localhost:8080/igraph/example1.html进入图导航器可视化界面,如图:(由于数据集中的图片链接现在已被豆瓣更改,很多节点的图片无法显示)

图导航器
可以拖动显示区域浏览全局大图。
图浏览器
浏览器打开http://localhost:8080/igraph/example2.html进入图浏览器可视化界面。
在搜索框中输入Movie:无间道,结果如图。

搜索结果
点击“无间道”,可以看到电影《无间道》对应的节点。

无间道
在图浏览器中,单击节点可以查看节点信息,双击可以展开节点。

图浏览器
关系查找器
浏览器打开http://localhost:8080/igraph/example3.html进入关系查找器可视化界面。在右侧输入起始节点Person:古天乐和结束节点Person:张家辉并选中搜索出的人物,设定最大路径长度为4,搜索路径,结果如图所示。共有20条路径,点击右侧路径列表可以对这条路径高亮显示。
关系查找器

