文章目錄
- 導讀
- 背景介紹
- 開始從零搭建知識圖譜所需的環境
-
- 大前提
- 想法
- Docker安裝
- Neo4j安裝
-
- 1、拉取鏡像
- 2、準備`docker-compose.yml`檔案
- 3、啟動
- 4、通路
- 5、Python包
- 問題分析
- 編碼實作
-
- 全域變量配置
- 資料讀取
- 建立節點
- 建立關系
- 整合
- 最後給個主函數
- 運作
導讀
本篇文章轉載自
Voyager-m
的部落格:知識圖譜-用python操縱neo4j資料庫-以高速收費站記錄為例。已獲得原文作者轉載許可。本篇與原篇的差別其實隻是在一些循環的代碼上進行了簡化,讓看起來很傳統的代碼縮減了很多。
背景介紹
讓我們來想像這樣一個場景:
突然有一天,國家突然要查這段高速公路在這段時間内的收費情況,包括車輛租賃、車輛通行等等的資料,然後經過抽樣調查就查到了我們現在需要進行學習的資料:點選這裡跳轉到
GitHub
檢視資料源。如果你需要,請放心下載下傳,這些都是開源的。
開始從零搭建知識圖譜所需的環境
好的,最耗時間的資料集準備已經結束了。我們直接開始吧。
因為并不知道人家查證是怎麼查,是以這裡就随便建構一下,說明一下建構的過程就夠了。我們的目的是學習方法,不是抓犯人
為了能夠讓所有的人都能夠上手,我們就從一台光秃秃的電腦開始。
大前提
先說明一下,我使用的環境是:
-
20.04 20.04 20.04系統Ubuntu
-
3.8.5 3.8.5 3.8.5Python
-
1.52.1 1.52.1 1.52.1+Microsoft Visual Studio
拓展包Python
-
4.2.1 4.2.1 4.2.1neo4j
想法
為了簡化部署過程,這裡就使用
Docker
部署
neo4j
,減少很多本地配置的坑。後來經過實踐發現,
Docker Hub
裡面的官方鏡像并沒有内置
Vim
或者
Vi
,而且
apt
指令執行得究極無敵棒槌慢,是以,盡量不要進入
Docker
修改配置。
Docker安裝
這個就直接參考我之前的安裝部落格,不再贅述啦。
點我檢視
Windows
版
Docker
安裝
點我檢視
Ubuntu
版
Docker
安裝
Neo4j安裝
既然是什麼都友善的
Docker
,那麼自然步驟就是:
1、拉取鏡像
docker pull neo4j
2、準備 docker-compose.yml
檔案
docker-compose.yml
為了友善,我就在本機部署的,于是放在了
/usr/local/docker/neo4j
這個目錄下
# 以下配置可以相容2.7到3.5的所有版本
version: '3.3'
# 服務
services:
# neo4j服務
neo4j:
# 鏡像來源
image: 'neo4j'
# 随着我的實體機的重新開機而重新開機
restart: always
# 使用exec指令進去後顯示的主機名稱
hostname: 'Neo4j-11xx'
# 在實體機的docker清單中顯示名稱
container_name: 'neo4j_11xx'
# 開啟的端口
ports:
# 管理界面通路端口
- '1174:7474'
# 資料傳輸端口
- '1187:7687'
# 磁盤映射
volumes:
- /usr/local/docker/neo4j/data:/data
3、啟動
docker-compose up -d
4、通路
打開浏覽器(雖然知道是廢話,但還是叮囑一句:
Windows
使用者别用
IE
打開)
然後通路
http://localhost:1174
這個網址(我們剛剛在
docker-compose.yml
中開啟的是這個端口)。
初始使用者名是
neo4j
,初始密碼是
neo4j
,初始資料庫是
neo4j
。不寫是哪個資料庫将會預設進入
neo4j
資料庫。對于小白來說,保持空白就好了。
5、Python包
在實體機内,
Windows
使用者可能需要使用
Git Bash
視窗進行包的安裝,而
Ubuntu
直接使用
Ctrl+Alt+T
呼出終端安裝,指令都是一樣的:
pip3 install py2neo
這裡就做一回強迫症,直接下最新的,别考慮最早支援的版本。
問題分析
- 如果網址進不去,先考慮是不是端口号輸錯了,比如明明你從 1174 1174 1174端口能夠打開登入界面,卻在登入界面使用 7474 7474 7474端口通路資料庫。這就像是明明知道你得的是感冒,卻拿了一瓶跌打油;
- 接着再考慮一下是不是鏡像選錯了。雖然
中的鏡像很多,但還是盡量使用官方鏡像,因為有足夠豐富的文檔支撐。Docker Hub
編碼實作
好了,到這裡,環境搭完了,我們就開始吧。
全域變量配置
# 配置類
class CONFIG(enumerate):
# Neo4j通路位址
URL = 'http://localhost:1174'
# 使用者名
USERNAME = 'neo4j'
# 密碼
PASSWORD = 'ljx62149079'
# xls檔案路徑
XLS = os.getcwd() + '/knowledge/data.xls'
# csv檔案路徑
CSV = os.getcwd() + '/knowledge/data.csv'
pass
資料讀取
還是老朋友
pandas
:
# 資料導入類
class DataImporter:
# 類構造器
def __init__(self):
# 直接從Excel裡面讀取所有的原生資料
# self.raw_data = pd.read_excel(CONFIG.XLS)
self.raw_data = pd.read_csv(CONFIG.CSV)
# 将所有的資料提取到一維數組中(去重)
self.all_data = list(
# 使用集合去掉重複的
set(
[
# 将一維數組所有的資料化為字元串
str(i) for i in list(
# 将二維數組改為一維數組
itertools.chain(
# 根據列屬性一一列出表格中所有的行資料
*[item for item in self.raw_data[[
# 列出所有的列屬性
column for column in self.raw_data.columns
]].values]
)
)
]
)
)
# 所有的購買方(去重)
self.buyer_list = list(set(self.raw_data['購買方名稱']))
# 所有的銷售方(去重)
self.seller_list = list(set(self.raw_data['銷售方名稱']))
# 所有原生資料的映射
self.dict = pd.DataFrame({
# 所有的金額(原生)
'finance': list(self.raw_data['金額']),
# 所有的購買方(原生)
'buyer': list(self.raw_data['購買方名稱']),
# 所有的銷售方(原生)
'seller': list(self.raw_data['銷售方名稱'])
})
'''
别忘了加上neo4j資料庫通路
'''
# 圖資料庫對象
self.graph = Graph(
CONFIG.URL,
username=CONFIG.USERNAME,
password=CONFIG.PASSWORD
)
# 清空緩存
self.graph.delete_all()
# 配對器
self.matcher = NodeMatcher(self.graph)
pass
建立節點
既然資料讀取可以了,那麼我們就可以繼續在類裡面添加方法:
class DataImporter:
# 傳入購買方、銷售方資料
def create_tree_node(self, buyers, sellers):
for key in buyers: # 根據購買方建立節點
self.graph.create(
Node('buyer', name=key)
)
pass
for key in sellers: # 根據銷售方建立節點
self.graph.create(
Node('seller', name=key)
)
pass
pass
pass
建立關系
class DataImporter:
def create_nodes_relation(self):
# 對于字典中所有的資料
for item in range(0, len(self.dict)):
try:
self.graph.create(
# 關系映射
Relationship(
self.matcher.match('buyer')
.where("_.name='" + self.dict['buyer'][item] + "'")
.first(),
self.dict['finance'][item],
self.matcher.match('seller')
.where("_.name='" + self.dict['seller'][item] + "'")
.first()
)
)
pass
# 如果出錯,顯示錯誤。增強程式健壯性
except AttributeError as ae:
print(ae, item)
pass
pass
pass
pass
整合
既然我們把零零碎碎的東西農好了之後,我們就開始整合:
# -*- coding: utf-8 -*-
import pandas as pd
import itertools
import os
from py2neo import Node, Graph, Relationship, NodeMatcher, data
# 配置類
class CONFIG(enumerate):
# Neo4j通路位址
URL = 'http://localhost:1174'
# 使用者名
USERNAME = 'neo4j'
# 密碼
PASSWORD = 'ljx62149079'
# xls檔案路徑
XLS = os.getcwd() + '/knowledge/data.xls'
# csv檔案路徑
CSV = os.getcwd() + '/knowledge/data.csv'
pass
# 資料導入類
class DataImporter:
# 類構造器
def __init__(self):
# 直接從Excel裡面讀取所有的原生資料
# self.raw_data = pd.read_excel(CONFIG.XLS)
self.raw_data = pd.read_csv(CONFIG.CSV)
# 将所有的資料提取到一維數組中(去重),沒用...
# self.all_data = list(set([str(i) for i in list(itertools.chain(*[item for item in self.raw_data[[column for column in self.raw_data.columns]].values]))]))
# 所有的購買方(去重)
self.buyer_list = list(set(self.raw_data['購買方名稱']))
# 所有的銷售方(去重)
self.seller_list = list(set(self.raw_data['銷售方名稱']))
# 所有原生資料的映射
self.dict = pd.DataFrame({
# 所有的金額(原生)
'finance': list(self.raw_data['金額']),
# 所有的購買方(原生)
'buyer': list(self.raw_data['購買方名稱']),
# 所有的銷售方(原生)
'seller': list(self.raw_data['銷售方名稱'])
})
# 圖資料庫對象
self.graph = Graph(
CONFIG.URL,
username=CONFIG.USERNAME,
password=CONFIG.PASSWORD
)
# 清空緩存
self.graph.delete_all()
# 配對器
self.matcher = NodeMatcher(self.graph)
pass
# 建立節點方法
def create_tree_node(self, buyers, sellers):
for key in buyers: # 根據購買方建立節點
self.graph.create(
Node('buyer', name=key)
)
pass
for key in sellers: # 根據銷售方建立節點
self.graph.create(
Node('seller', name=key)
)
pass
pass
# 建立節點間關系
def create_nodes_relation(self):
# 對于字典中所有的資料
for item in range(0, len(self.dict)):
try:
self.graph.create(
Relationship(self.matcher.match('buyer').where("_.name='" + self.dict['buyer'][item] + "'").first(), self.dict['finance'][item], self.matcher.match('seller').where("_.name='" + self.dict['seller'][item] + "'").first())
)
pass
# 如果出錯,顯示錯誤,增強程式健壯性
except AttributeError as ae:
print(ae, item)
pass
pass
pass
pass
這段你可以在我的
GitHub
中下載下傳
最後給個主函數
if __name__ == '__main__':
# 資料導入類
dataImpoter = DataImporter()
# 建立實體節點
dataImpoter.create_tree_node(dataImpoter.buyer_list, dataImpoter.seller_list)
# 建立實體節點間的關系
dataImpoter.create_nodes_relation()
pass
運作
運作之後,啥都沒有,就退出了。
你覺得失敗了?當然沒有,我們進入浏覽器看看:
http://localhost:1174
,會發現一個界面:
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiIXZ05WZj91YpB3IwczX0xiRGZkRGZ0Xy9GbvNGL2EzXlpXazxSN1IjY5pkMYVjSYlVdsdkW5ljMMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2X0hXZ0xCMx81dvRWYoNHLrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnLzcjNwUzNyMjM4ATMwEjMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
在網址欄下面有個灰色的地方,有個淡淡的
neo4j$
(得仔細看),我們在這裡輸入:
MATCH p=()-->() RETURN p LIMIT 25
點選正右端的三角形,也就是運作按鈕;如果你想友善也可以按回車。于是能夠看到:
這就是
neo4j
給出的知識圖譜。
看起來還不錯!
是不是有點能了解了呢?