天天看點

知識圖譜:小小的入門級綜合應用導讀背景介紹開始從零搭建知識圖譜所需的環境編碼實作整合最後給個主函數運作

文章目錄

  • 導讀
  • 背景介紹
  • 開始從零搭建知識圖譜所需的環境
    • 大前提
    • 想法
    • Docker安裝
    • Neo4j安裝
      • 1、拉取鏡像
      • 2、準備`docker-compose.yml`檔案
      • 3、啟動
      • 4、通路
      • 5、Python包
      • 問題分析
  • 編碼實作
    • 全域變量配置
    • 資料讀取
    • 建立節點
    • 建立關系
  • 整合
  • 最後給個主函數
  • 運作

導讀

本篇文章轉載自

Voyager-m

的部落格:知識圖譜-用python操縱neo4j資料庫-以高速收費站記錄為例。已獲得原文作者轉載許可。本篇與原篇的差別其實隻是在一些循環的代碼上進行了簡化,讓看起來很傳統的代碼縮減了很多。

背景介紹

讓我們來想像這樣一個場景:

突然有一天,國家突然要查這段高速公路在這段時間内的收費情況,包括車輛租賃、車輛通行等等的資料,然後經過抽樣調查就查到了我們現在需要進行學習的資料:點選這裡跳轉到

GitHub

檢視資料源。如果你需要,請放心下載下傳,這些都是開源的。

開始從零搭建知識圖譜所需的環境

好的,最耗時間的資料集準備已經結束了。我們直接開始吧。

因為并不知道人家查證是怎麼查,是以這裡就随便建構一下,說明一下建構的過程就夠了。我們的目的是學習方法,不是抓犯人

為了能夠讓所有的人都能夠上手,我們就從一台光秃秃的電腦開始。

大前提

先說明一下,我使用的環境是:

  • Ubuntu

    20.04 20.04 20.04系統
  • Python

    3.8.5 3.8.5 3.8.5
  • Microsoft Visual Studio

    1.52.1 1.52.1 1.52.1+

    Python

    拓展包
  • neo4j

    4.2.1 4.2.1 4.2.1

想法

為了簡化部署過程,這裡就使用

Docker

部署

neo4j

,減少很多本地配置的坑。後來經過實踐發現,

Docker Hub

裡面的官方鏡像并沒有内置

Vim

或者

Vi

,而且

apt

指令執行得究極無敵棒槌慢,是以,盡量不要進入

Docker

修改配置。

Docker安裝

這個就直接參考我之前的安裝部落格,不再贅述啦。

點我檢視

Windows

Docker

安裝

點我檢視

Ubuntu

Docker

安裝

Neo4j安裝

既然是什麼都友善的

Docker

,那麼自然步驟就是:

1、拉取鏡像

docker pull neo4j
           

2、準備

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

,會發現一個界面:

知識圖譜:小小的入門級綜合應用導讀背景介紹開始從零搭建知識圖譜所需的環境編碼實作整合最後給個主函數運作

在網址欄下面有個灰色的地方,有個淡淡的

neo4j$

(得仔細看),我們在這裡輸入:

MATCH p=()-->() RETURN p LIMIT 25
           

點選正右端的三角形,也就是運作按鈕;如果你想友善也可以按回車。于是能夠看到:

知識圖譜:小小的入門級綜合應用導讀背景介紹開始從零搭建知識圖譜所需的環境編碼實作整合最後給個主函數運作

這就是

neo4j

給出的知識圖譜。

看起來還不錯!

是不是有點能了解了呢?