创新实训周报2024.5.19

 2024.5.19 可视化方面的探索

结合前端的需求,我需要将爬取的文档和关系数据进行一定的格式转化以便于可视化展示。

知识图谱数据格式转换

1. 概述

该工作主要功能是处理一个包含文档标题和实体名称的 JSON 文件,生成一个包含节点(文档标题)和边(文档标题与实体名称关系)的知识图谱(KG)。生成的知识图谱按特定类别(如物理层、数据链路层等)进行分类,并将结果输出到一个 JSON 文件中。

2. 代码功能简介

代码执行以下主要任务:

  1. 从输入的 JSON 文件中读取数据。
  2. 创建节点和边,并构建一个图结构。
  3. 按照预定义的类别对节点进行分类。
  4. 将处理后的图结构数据存储到一个 JSON 文件中。

3. 数据格式转换分析

输入数据格式

输入数据来自一个名为 computer_network_mentions_with_title.json 的文件,其中每行是一个 JSON 对象,包含以下字段:

  • doc_title: 文档标题
  • entity_name: 实体名称
输出数据格式

输出是一个 JSON 对象,包含以下结构:

  • categories: 节点类别列表
  • nodes: 节点列表,每个节点包含名称、值和类别
  • links: 边列表,每个边包含源节点和目标节点

4. 实现思路

  1. 初始化类别和数据结构:首先定义类别列表,并初始化存储节点、节点ID映射、图结构和边的相关数据结构。
  2. 读取并解析输入文件:逐行读取输入文件,将每个文档标题和实体名称映射到节点和边的数据结构中。
  3. 构建图结构:根据文档标题和实体名称的关系构建图结构,并记录每个文档标题的实体名称。
  4. 分类节点:基于预定义的类别,通过广度优先搜索(BFS)方法,将相关节点进行分类,并构建节点之间的边。
  5. 输出结果:将最终构建的图结构数据写入到一个 JSON 文件中。
读取并解析输入文件
f = open('./computer_network_mentions_with_title.json', 'r', encoding='utf-8')
last_title = ''
for line in f:
    item = json.loads(line)
    if item['doc_title'] not in nodes_id.keys():
        nodes_id[item['doc_title']] = len(nodes)
        nodes.append({
            "name": item['doc_title'],
            "value": 1,
            "category": 7
        })
        graph[item['doc_title']] = []
    edges.append((item['doc_title'], item['entity_name']))
    graph[item['doc_title']].append(item['entity_name'])
    if len(nodes) == 1000:
        break
  • 打开输入文件,逐行读取并解析为 JSON 对象。
  • 对每个文档标题,检查是否已经在 nodes_id 中,如不存在则添加到 nodesnodes_id 中,并初始化 graph 字典。
  • 添加文档标题与实体名称的关系到 edges 列表和 graph 字典中。
  • 当节点数量达到 1000 时,停止读取。
构建图结构
for id, categorie in enumerate(tqdm(categories)):
    now_title = categorie['name']
    max_dis = 2
    que = [(now_title, 0)]
    vis = set()
    now = 0
    while now < len(que):
        now_title, now_dis = que[now]
        now += 1
        if now_title in nodes_id.keys():
            nodes[nodes_id[now_title]]['category'] = id
        if now_dis < max_dis:
            if now_title in graph.keys():
                for new_title in graph[now_title]:
                    if new_title not in vis:
                        que.append([new_title, now_dis + 1])
                        vis.add(new_title)
                        if now_title in nodes_id.keys() and new_title in nodes_id.keys():
                            links.append({
                                "source": nodes_id[now_title],
                                "target": nodes_id[new_title]
                            })
  • 使用广度优先搜索(BFS)方法,从每个类别的名称开始,遍历其相关的文档标题和实体名称,将节点分类并构建边。
  • max_dis 参数限制了搜索深度,确保仅搜索与类别名称相关的节点及其直接连接的节点。
输出结果
kg = {
    "categories": categories,
    "nodes": nodes,
    "links": links
}

out_f = open("./kg_by_category.json", 'w', encoding='utf-8')
out_f.write(json.dumps(kg, ensure_ascii=False))
  • 构建最终的知识图谱数据结构,包括 categoriesnodeslinks
  • 将知识图谱数据写入到 kg_by_category.json 文件中。

实现效果

章节实体数目统计

1. 初始化部分

代码首先初始化了几个变量和数据结构:

  • categories:一个包含了各个网络层级及其他分类的列表。
  • nodes:用于存储所有的文档节点。
  • nodes_id:用于记录文档节点的唯一ID。
  • graph:用于存储文档节点之间的关系。
  • edgeslinks:用于存储文档节点与实体之间的边和链接关系。
categories = [
    {"name": "物理层", "keyword": {}, "base": "物理层"},
    {"name": "数据链路层", "keyword": {}, "base": "数据链路层"},
    {"name": "介质访问控制", "keyword": {}, "base": "介质访问控制"},
    {"name": "网络层", "keyword": {}, "base": "网络层"},
    {"name": "传输层", "keyword": {}, "base": "传输层"},
    {"name": "应用层", "keyword": {}, "base": "应用层"},
    {"name": "其他", "keyword": {}, "base": "其他"}
]

nodes = []
nodes_id = {}
graph = {}
edges = []
links = []

 

2. 读取文件并构建图结构

代码从文件./computer_network_mentions_with_title.json中读取数据,并构建文档节点和实体之间的关系图:

  • 如果文档标题不在nodes_id中,则将其添加到nodes列表和nodes_id字典中。
  • 更新graph字典以记录文档节点与实体节点的关系。
  • 构建edges列表来记录文档与实体之间的边。
f = open('./computer_network_mentions_with_title.json', 'r', encoding='utf-8')
for line in f:
    item = json.loads(line)
    if item['doc_title'] not in nodes_id.keys():
        nodes_id[item['doc_title']] = len(nodes)
        nodes.append({
            "name": item['doc_title'],
            "value": 1,
            "category": 7
        })
        graph[item['doc_title']] = []
    edges.append((item['doc_title'], item['entity_name']))
    graph[item['doc_title']].append(item['entity_name'])
    if len(nodes) == 1000:
        break
3. 统计章节相关实体数量

接下来,代码按章节统计了相关实体的数量:

  • 遍历每一个章节categories,对每一个章节进行广度优先搜索(BFS),以统计与该章节相关的实体数量。
  • 对每一个章节的实体节点进行遍历,记录访问过的节点,并更新节点类别。
  • 在遍历过程中,记录章节与实体节点之间的链接关系。
data = []
for id, categorie in enumerate(tqdm(categories)):
    now_title = categorie['name']
    max_dis = 2
    que = [(now_title, 0)]
    vis = set()
    now = 0
    sum = 0
    while now < len(que):
        now_title, now_dis = que[now]
        now += 1
        sum += 1
        if now_title in nodes_id.keys():
            nodes[nodes_id[now_title]]['category'] = id
        if now_dis < max_dis:
            if now_title in graph.keys():
                for new_title in graph[now_title]:
                    if new_title not in vis:
                        que.append([new_title, now_dis + 1])
                        vis.add(new_title)
                        if now_title in nodes_id.keys() and new_title in nodes_id.keys():
                            links.append({
                                "source": nodes_id[now_title],
                                "target": nodes_id[new_title]
                            })
    data.append({
        'value': sum,
        'name': categorie['name']
    })
4. 输出结果

最后,代码将统计结果输出到文件./chapter_statistics.json中,以JSON格式保存:

out_f = open("./chapter_statistics.json", 'w', encoding='utf-8')
out_f.write(json.dumps(data, ensure_ascii=False))
5.效果

章节关系建模

1. 初始化部分

代码首先初始化了几个变量和数据结构:

  • categories:一个包含了各个网络层级及其他分类的列表。
  • nodes:用于存储所有的文档节点。
  • nodes_id:用于记录文档节点的唯一ID。
  • graph:用于存储文档节点之间的关系。
  • edgeslinks:用于存储文档节点与实体之间的边和链接关系。
categories = [
    {"name": "物理层", "keyword": {}, "base": "物理层"},
    {"name": "数据链路层", "keyword": {}, "base": "数据链路层"},
    {"name": "介质访问控制", "keyword": {}, "base": "介质访问控制"},
    {"name": "网络层", "keyword": {}, "base": "网络层"},
    {"name": "传输层", "keyword": {}, "base": "传输层"},
    {"name": "应用层", "keyword": {}, "base": "应用层"},
    {"name": "其他", "keyword": {}, "base": "其他"}
]

nodes = []
nodes_id = {}
graph = {}
edges = []
links = []
2. 读取文件并构建图结构

代码从文件./computer_network_mentions_with_title.json中读取数据,并构建文档节点和实体之间的关系图:

  • 如果文档标题不在nodes_id中,则将其添加到nodes列表和nodes_id字典中。
  • 更新graph字典以记录文档节点与实体节点的关系。
  • 构建edges列表来记录文档与实体之间的边。
f = open('./computer_network_mentions_with_title.json', 'r', encoding='utf-8')
for line in f:
    item = json.loads(line)
    if item['doc_title'] not in nodes_id.keys():
        nodes_id[item['doc_title']] = len(nodes)
        nodes.append({
            "name": item['doc_title'],
            "value": 1,
            "category": 7
        })
        graph[item['doc_title']] = []
    edges.append((item['doc_title'], item['entity_name']))
    graph[item['doc_title']].append(item['entity_name'])
    if len(nodes) == 1000:
        break
3. 过滤和连接章节节点

代码通过广度优先搜索(BFS)对章节节点间的关系进行过滤和连接:

  • 遍历每一个章节categories,对每一个章节进行广度优先搜索,以统计与该章节相关的实体节点。
  • 对每一个章节的实体节点进行遍历,记录访问过的节点,并更新节点类别。
  • 在遍历过程中,记录章节与实体节点之间的链接关系。
for id, categorie in enumerate(tqdm(categories)):
    now_title = categorie['name']
    max_dis = 2
    que = [(now_title, 0)]
    vis = set()
    vis.add(now_title)
    now = 0
    while now < len(que):
        now_title, now_dis = que[now]
        now += 1
        if now_title in nodes_id.keys():
            nodes[nodes_id[now_title]]['category'] = id
        if now_dis < max_dis:
            if now_title in graph.keys():
                for new_title in graph[now_title]:
                    if new_title not in vis:
                        que.append([new_title, now_dis + 1])
                        vis.add(new_title)
                        if now_title in nodes_id.keys() and new_title in nodes_id.keys():
                            links.append({
                                "source": nodes_id[now_title],
                                "target": nodes_id[new_title]
                            })
4. 输出结果

最后,代码将构建的知识图谱(包括节点、链接和分类信息)输出到文件./kg_by_category.json中,以JSON格式保存:

kg = {
    "categories": categories,
    "nodes": nodes,
    "links": links
}

out_f = open("./kg_by_category.json", 'w', encoding='utf-8')
out_f.write(json.dumps(kg, ensure_ascii=False))
 5. 结果

树形结构的可视化

概述

读取一个包含文档标题和实体名称的 JSON 文件,将其转换成树形结构的数据,并将每个文档标题及其子树结构存储到单独的 JSON 文件中。输出的 JSON 文件适用于可视化工具,如 d3.js,用于展示树形结构图。

主要任务
  1. 读取并解析输入 JSON 文件。
  2. 维护一个顺序列表 order 和一个字典 sons,记录每个文档标题及其关联的实体名称。
  3. 生成树形结构数据。
  4. 将树形结构数据保存到单独的 JSON 文件中,每个文件对应一个文档标题。

数据格式转换分析
输入数据格式

输入数据来自一个名为 computer_network_mentions_with_title.json 的文件,其中每行是一个 JSON 对象,包含 doc_titleentity_name

输出数据格式

输出是树形结构的 JSON 对象,每个对象包含 namesizechildrenvalue 属性。输出文件以 id.json 命名存储在 tree_data 目录中。

实现思路
  1. 初始化必要的数据结构。
  2. 读取输入文件并解析数据,将每个文档标题和其关联的实体名称存储到 ordersons 中。
  3. 按照预定义的规则生成树形结构数据。
  4. 将每个文档标题及其树形结构数据存储到单独的 JSON 文件中。
生成树形结构数据
id = 0
for fa in order:
    item = {
        "name": '',
        "size": 0,
        "children": [],
        "value": 0
    }
    fasize = 0
    for s1 in sons[fa]:
        if len(item['children']) == 10:
            break
        if s1 in sons.keys():
            s1item = {
                "name": '',
                "size": 0,
                "children": [],
                "value": 0
            }
            s1size = 0
            for s2 in sons[s1]:
                if len(s1item['children']) == 10:
                    break
                if s2 in sons.keys():
                    s2item = {}
                    s2size = random.randrange(1, 100)
                    s1size += s2size
                    s2item['name'] = s2
                    s2item['size'] = s2size
                    s2item['value'] = s2size
                    s1item['children'].append(s2item)
            s1item['name'] = s1
            s1item['size'] = s1size
            s1item['value'] = s1size
            fasize += s1size
            item['children'].append(s1item)
    item['name'] = fa
    item['size'] = fasize
    item['value'] = fasize
    out_f = open("./tree_data/" + str(id) + ".json", "w", encoding='utf-8')
    out_f.write(json.dumps(item, ensure_ascii=False))
    id += 1 
    print(id)
    if id == 2000:
        break
  • 初始化 id 计数器。
  • 对于每个文档标题 fa,创建一个包含 namesizechildrenvalue 的空字典 item
  • 对于每个与文档标题关联的实体名称 s1,如果它也是一个文档标题,则创建一个类似的字典 s1item
  • 对于每个与 s1 关联的实体名称 s2,生成一个随机大小 s2size,并将其添加到 s1itemchildren 中。
  • 更新 s1itemsizevalue,并将其添加到 itemchildren 中。
  • 更新 itemsizevalue,并将其写入到一个以 id 命名的 JSON 文件中。
数据展示
{"name": "计算机网络", "size": 5290, "children": [{"name": "地理位置", "size": 604, "children": [{"name": "地理事物", "size": 67, "value": 67}, {"name": "空间关系", "size": 58, "value": 58}, {"name": "确定", "size": 46, "value": 46}, {"name": "经纬度", "size": 83, "value": 83}, {"name": "经济地理位置", "size": 65, "value": 65}, {"name": "地理事物", "size": 99, "value": 99}, {"name": "空间关系", "size": 43, "value": 43}, {"name": "测绘科学与技术", "size": 81, "value": 81}, {"name": "地理事物", "size": 43, "value": 43}, {"name": "定性", "size": 19, "value": 19}], "value": 604}, {"name": "外部设备", "size": 543, "children": [{"name": "外设", "size": 9, "value": 9}, {"name": "输出设备", "size": 76, "value": 76}, {"name": "外存储器", "size": 78, "value": 78}, {"name": "作用", "size": 73, "value": 73}, {"name": "外围设备", "size": 72, "value": 72}, {"name": "主机", "size": 1, "value": 1}, {"name": "设备", "size": 49, "value": 49}, {"name": "系统", "size": 20, "value": 20}, {"name": "外设", "size": 99, "value": 99}, {"name": "计算机硬件", "size": 66, "value": 66}], "value": 543}, {"name": "通信线路", "size": 547, "children": [{"name": "有线通信", "size": 4, "value": 4}, {"name": "传输媒介", "size": 99, "value": 99}, {"name": "巴尔的摩", "size": 37, "value": 37}, {"name": "英吉利海峡", "size": 94, "value": 94}, {"name": "海底电缆", "size": 68, "value": 68}, {"name": "海底电缆", "size": 87, "value": 87}, {"name": "丹麦大北电报公司", "size": 44, "value": 44}, {"name": "多模光纤", "size": 68, "value": 68}, {"name": "单模光纤", "size": 3, "value": 3}, {"name": "传输媒介", "size": 43, "value": 43}], "value": 547}, {"name": "网络操作系统", "size": 515, "children": [{"name": "计算机", "size": 95, "value": 95}, {"name": "操作系统", "size": 4, "value": 4}, {"name": "服务器", "size": 49, "value": 49}, {"name": "客户端", "size": 26, "value": 26}, {"name": "服务器", "size": 63, "value": 63}, {"name": "资源", "size": 62, "value": 62}, {"name": "计算机", "size": 31, "value": 31}, {"name": "NOS", "size": 90, "value": 90}, {"name": "工作站", "size": 64, "value": 64}, {"name": "单用户操作系统", "size": 31, "value": 31}], "value": 515}, {"name": "网络管理软件", "size": 573, "children": [{"name": "网络管理", "size": 67, "value": 67}, {"name": "支撑软件", "size": 93, "value": 93}, {"name": "网络设备", "size": 22, "value": 22}, {"name": "网络系统", "size": 53, "value": 53}, {"name": "体系结构", "size": 13, "value": 13}, {"name": "应用程序", "size": 79, "value": 79}, {"name": "网络搜索", "size": 45, "value": 45}, {"name": "Windows NT", "size": 18, "value": 18}, {"name": "网络管理软件", "size": 93, "value": 93}, {"name": "网络管理协议", "size": 90, "value": 90}], "value": 573}, {"name": "网络通信协议", "size": 736, "children": [{"name": "操作系统", "size": 85, "value": 85}, {"name": "体系结构", "size": 84, "value": 84}, {"name": "互联网络", "size": 54, "value": 54}, {"name": "网络", "size": 81, "value": 81}, {"name": "操作系统", "size": 54, "value": 54}, {"name": "体系结构", "size": 90, "value": 90}, {"name": "互联网络", "size": 82, "value": 82}, {"name": "TCP/IP", "size": 86, "value": 86}, {"name": "传输控制协议", "size": 55, "value": 55}, {"name": "网际协议", "size": 65, "value": 65}], "value": 736}, {"name": "资源共享", "size": 437, "children": [{"name": "计算机", "size": 46, "value": 46}, {"name": "操作系统", "size": 53, "value": 53}, {"name": "共享空间", "size": 38, "value": 38}, {"name": "局域网", "size": 61, "value": 61}, {"name": "打印服务器", "size": 84, "value": 84}, {"name": "邮件服务器", "size": 66, "value": 66}, {"name": "局域网", "size": 28, "value": 28}, {"name": "集中存储", "size": 7, "value": 7}, {"name": "网络存储", "size": 47, "value": 47}, {"name": "工作组", "size": 7, "value": 7}], "value": 437}, {"name": "信息传递", "size": 407, "children": [{"name": "现代化管理", "size": 58, "value": 58}, {"name": "电码", "size": 66, "value": 66}, {"name": "购买行为", "size": 6, "value": 6}, {"name": "销售管理", "size": 21, "value": 21}, {"name": "商品信息", "size": 38, "value": 38}, {"name": "购买行为", "size": 32, "value": 32}, {"name": "信息管理", "size": 38, "value": 38}, {"name": "信息活动", "size": 64, "value": 64}, {"name": "有机体", "size": 31, "value": 31}, {"name": "主体要素", "size": 53, "value": 53}], "value": 407}, {"name": "计算机系统", "size": 354, "children": [{"name": "存储信息", "size": 53, "value": 53}, {"name": "结果信息", "size": 21, "value": 21}, {"name": "计算机", "size": 4, "value": 4}, {"name": "硬件", "size": 18, "value": 18}, {"name": "软件", "size": 27, "value": 27}, {"name": "中央处理机", "size": 62, "value": 62}, {"name": "存储器", "size": 61, "value": 61}, {"name": "外部设备", "size": 12, "value": 12}, {"name": "系统软件", "size": 83, "value": 83}, {"name": "应用软件", "size": 13, "value": 13}], "value": 354}, {"name": "计算机通信网", "size": 574, "children": [{"name": "通信设备", "size": 86, "value": 86}, {"name": "数据传输", "size": 58, "value": 58}, {"name": "领域", "size": 87, "value": 87}, {"name": "条件", "size": 76, "value": 76}, {"name": "通信技术", "size": 6, "value": 6}, {"name": "微电子", "size": 86, "value": 86}, {"name": "数据传输", "size": 19, "value": 19}, {"name": "处理器", "size": 50, "value": 50}, {"name": "功能", "size": 10, "value": 10}, {"name": "资源共享", "size": 96, "value": 96}], "value": 574}], "value": 5290}

 

实现结果

  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值