使用Neo4j+InteractiveGraph实现豆瓣电影知识图谱可视化
0.介紹
本文基于豆瓣電影數據構建了一個電影知識圖譜。其中包括電影、演員、導演三種節點及相關關系。并使用InteractiveGraph對圖譜完成可視化工作。
- 數據豐富,圖譜包含2.7萬個節點,5萬條關系
- 使用Neo4j圖數據庫進行圖存儲
- 支持大圖全局可視化預覽
- 支持節點關聯發現
- 支持節點展開瀏覽可視化
所用到的程序包括:
- Tomcat 8.5
- Neo4j 社區版3.5.12
- InteractiveGraph 0.3.2 (項目地址:https://github.com/grapheco/InteractiveGraph) 歡迎star!!!
- InteractiveGraph-neo4j 0.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目錄中,并啟動Neo4j。
使用如下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)/103.配置可視化系統
本文使用的知識圖譜可視化系統包括兩個部分:InteractiveGraph和InteractiveGraph-neo4j,前者為可視化系統的Web前端部分,負責顯示和交互;后者為可視化系統的后端部分,負責管理數據以及提供各種數據訪問接口。
InteractiveGraph-neo4j安裝與配置
下載與部署
首先從github下載最新的發行版war包:https://github.com/grapheco/InteractiveGraph-neo4j/releases
將下載完成的war包放到Tomcat的webapps目錄中,tomcat會自動解壓war包生成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條路徑,點擊右側路徑列表可以對這條路徑高亮顯示。
?
關系查找器
?
InteractiveGraph項目地址:
https://github.com/grapheco/InteractiveGraph?歡迎關注并點贊!!
?????
總結
以上是生活随笔為你收集整理的使用Neo4j+InteractiveGraph实现豆瓣电影知识图谱可视化的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 超硬核!兔兔阿里p7学长给的面试知识库
- 下一篇: 又一款超好用开源知识库管理工具