坦克世界WOT知识图谱之知识图谱篇

文章目录

  • 关于Neo4j
  • 1. neo4j安装及配置:
  • 2. 确定三元组
  • 3. 代码实现
  • 结束语

关于Neo4j

  Neo4j是一个高性能的,NOSQL图形数据库。它是一个嵌入式的、基于磁盘的、具备完全的事务特性的Java持久化引擎,但是它将结构化数据存储在网络(从数学角度叫做图)上而不是表中。是构建知识图谱最常用的图数据库之一。

  知识图谱部署在Linux服务器上,具体版本信息为:
  Ubuntu 22.04.2
  Java 17.0.8
  Neo4j 5.12.0

坦克世界WOT知识图谱之知识图谱篇_第1张图片

1. neo4j安装及配置:

  Neo4j依赖Java引擎,因此需要安装Java

  Java17官方地址:https://www.oracle.com/java/technologies/downloads/#java17

坦克世界WOT知识图谱之知识图谱篇_第2张图片

  Neo4j官方地址:https://neo4j.com/deployment-center/#community

坦克世界WOT知识图谱之知识图谱篇_第3张图片
  安装流程:

# 下载java17
wget https://download.oracle.com/java/17/latest/jdk-17_linux-x64_bin.tar.gz
# 下载neo4j
https://dist.neo4j.org/neo4j-community-5.12.0-unix.tar.gz

# 解压到/usr/local
sudo tar -zxvf jdk-17_linux-x64_bin.tar.gz -C /usr/local/
sudo tar -zxvf neo4j-community-5.12.0-unix.tar.gz -C /usr/local/

  配置流程:

# 配置neo4j
vim /usr/local/neo4j-community-5.12.0/conf/neo4j.conf
# line 65 设置远程访问
server.default_listen_address=0.0.0.0
# line 86, 91 设置端口
server.bolt.listen_address=:7687
server.http.listen_address=:7474
# 7687是bolt端口,Bolt协议是neo4j的应用层协议
# 7474和7473分别是http和https端口,可以通过浏览器来访问可视化界面

# 配置环境变量
vim ~/.bashrc
# >>> setting neo4j >>>
JAVA_HOME=/usr/local/jdk-17.0.8
NEO4J_HOME=/usr/local/neo4j-community-5.12.0
export PATH=$JAVA_HOME/bin:$NEO4J_HOME/bin:$PATH
# <<< setting neo4j <<<

# 使配置生效
source ~/.bashrc

# 查看版本
java --version
neo4j --version

  版本信息如下:

坦克世界WOT知识图谱之知识图谱篇_第4张图片

  以下是neo4j常用的几个指令:

# 启动neo4j
neo4j start
# 查看neo4j的状态
neo4j status
# 停止neo4j
neo4j stop
# 重启neo4j
neo4j restart 

坦克世界WOT知识图谱之知识图谱篇_第5张图片

  ps: 如果因权限问题启动失败,则需要给予一定的权限:
  bash sudo chmod 777 -R neo4j-community-5.12.0 jdk-17.0.8

  浏览器访问可视化界面http://localhost:7474(可以修改为数据库的ip),初始账户及密码均为neo4j

坦克世界WOT知识图谱之知识图谱篇_第6张图片
  登录后会自动跳转让修改初始密码,修改完毕后进入可视化界面:

坦克世界WOT知识图谱之知识图谱篇_第7张图片

2. 确定三元组

  关于知识图谱中三元组的相关知识,这里也不再进行概述,感兴趣的可以查阅相关资料。
  本来计划按照如下方式进行构造知识图谱,但后来实现的过程中发现,不太好构造(其实还不太熟练哈哈哈哈),所以就构造简单了些,比如坦克的火力/机动性/防护/侦察这些属性直接展开了。

坦克世界WOT知识图谱之知识图谱篇_第8张图片
  展开后的关系如下:

# (实体, 关系, 实体)
Tank:
    系别:
    类型:
    等级:
    角色:
    性质:
    历史背景:
    
    银币:
    经验:
    
    损伤:
    装甲穿透力:
    火炮装填时间:
    最小弹震持续时间:
    最大弹震持续时间:
    射速:
    平均每分钟损伤:
    瞄准时间:
    00米精度:
    弹药容量:
    
    重量/最大载重量:
    发动机功率:
    单位功率:
    最大速度:
    旋转速度:
    炮塔旋转速度:
    
    生命值:
    车体装甲:
    炮塔装甲:
    悬挂装置维修时间:
    
    观察范围:
    通信距离:

3. 代码实现

  根据上篇博客爬取到的坦克数据,构造知识图谱:

# -*- coding: utf-8 -*-
# Author  : xiayouran
# Email   : [email protected]
# Datetime: 2023/10/1 20:29
# Filename: build_kg.py
import os
import json
from py2neo import Graph, Node, Relationship, NodeMatcher


class WOTKG(object):
    def __init__(self, clean_kg=True):
        self.clean_kg = clean_kg
        self.entity_tank = []
        self.entity_price = []
        self.entity_firepower = []
        self.entity_mobility = []
        self.entity_survivability = []
        self.entity_spotting = []
        self.all_entity = []
        self.data_path = '../data/tank_list_detail.json'

        self.graph = Graph('neo4j://172.20.203.172:7687', auth=('neo4j', 'lyp123456'))  # use your ip 172.20.197.99
        self.matcher = NodeMatcher(self.graph)
        if self.clean_kg:
            self.graph.delete_all()

    def build_KG(self):
        self.collect_entity()
        self.create_all_node()
        self.create_relation()

    def check_zero(self, v_str):
        if not v_str:
            return True
        elif len(v_str) == 2 and v_str[0] == '0' and v_str[1] in ['秒', '米', '%', '度']:
            return True
        else:
            return False

    def add_entity(self, tank_name, entity_name, v_item: dict):
        for k_, v_ in v_item.items():
            if self.check_zero(v_):
                continue
            if entity_name == 'Price':
                self.entity_price.append(('Price', k_, v_))
            elif entity_name == 'Firepower':
                self.entity_firepower.append(('Firepower', k_, v_))
            elif entity_name == 'Mobility':
                self.entity_mobility.append(('Mobility', k_, v_))
            elif entity_name == 'Survivability':
                self.entity_survivability.append(('Survivability', k_, v_))
            elif entity_name == 'Spotting':
                self.entity_spotting.append(('Spotting', k_, v_))
            self.all_entity.append((tank_name, entity_name, k_, v_))

    def collect_entity(self):
        with open(self.data_path, 'r', encoding='utf-8') as f:
            data_json = json.load(f)
        for tank_item in data_json.values():
            tank_name = tank_item['tank_name']
            for k, v in tank_item.items():
                if k[0] == 't' or not v:
                    continue
                if k == '价格':
                    if isinstance(v, str):
                        self.entity_price.append(('Price', '金币', v))
                        self.all_entity.append((tank_name, 'Price', '金币', v))
                    else:
                        self.add_entity(tank_name, 'Price', v)
                elif k == '火力':
                    self.add_entity(tank_name, 'Firepower', v)
                elif k == '机动性':
                    self.add_entity(tank_name, 'Mobility', v)
                elif k == '防护':
                    self.add_entity(tank_name, 'Survivability', v)
                elif k == '侦察':
                    self.add_entity(tank_name, 'Spotting', v)
                else:
                    self.entity_tank.append((tank_name, k, v))
                    self.all_entity.append((tank_name, 'Tank', k, v))

    def create_node(self, entity_list, entity_name='Tank'):
        head_nodes = []
        tail_nodes = []

        for (head, rela, tail) in entity_list:
            if head not in head_nodes and head not in ['Price', 'Firepower', 'Mobility', 'Survivability', 'Spotting']:
                head_nodes.append(head)
                node = Node(entity_name, name=head)
                self.graph.create(node)
            if tail not in tail_nodes:
                tail_nodes.append(tail)
                node = Node("{}Value".format(entity_name), name=tail)
                self.graph.create(node)

    def create_all_node(self):
        self.create_node(self.entity_tank, entity_name='Tank')
        self.create_node(self.entity_price, entity_name='Price')
        self.create_node(self.entity_firepower, entity_name='Firepower')
        self.create_node(self.entity_mobility, entity_name='Mobility')
        self.create_node(self.entity_survivability, entity_name='Survivability')
        self.create_node(self.entity_spotting, entity_name='Spotting')

    def create_relation(self):
        for (head, flag_str, rela, tail) in self.all_entity:
            node_head = self.matcher.match('Tank').where(name=head).first()
            node_tail = self.matcher.match('{}Value'.format(flag_str)).where(name=tail).first()
            rela_node = Relationship(node_head, rela, node_tail)
            self.graph.create(rela_node)


if __name__ == '__main__':
    wot_kg = WOTKG(clean_kg=True)
    wot_kg.build_KG()

  构造后的知识图谱可视化效果如下:
  单辆坦克:

坦克世界WOT知识图谱之知识图谱篇_第9张图片
  知识图谱局部:

坦克世界WOT知识图谱之知识图谱篇_第10张图片

结束语

  本篇的代码已经同步到仓库中,感兴趣的话可以拉取一下,下一篇文章就基于这个知识图谱来构造一个关于坦克百科的智能问答机器人。

开源代码仓库


  如果喜欢的话记得给我的GitHub仓库WOT点个Star哦!ヾ(≧∇≦*)ヾ


  公众号已开通:夏小悠,关注以获取更多关于Python文章、AI领域最新技术、LLM大模型相关论文及内部PPT等资料^_^

你可能感兴趣的:(Python爬虫,NLP,1024程序员节,人工智能,知识图谱,NLP,LLM)