Python写的GraphRAG生成的graphml文件转echarts脚本,方便用于查看GraphRAG生成的graphml文件。
如果不太明白用途的,可以查看上手GraphRAG心得(非GPT-4o跑通)
针对需要更复杂关系图谱或者更多样式的, 可以自行修改
html_template
中的html样式。
脚本
import xml.etree.ElementTree as ET
import json
import os
from jinja2 import Template
from tkinter import Tk
from tkinter import filedialog
# 解析GraphML文件
def parse_graphml(file_path):
tree = ET.parse(file_path)
root = tree.getroot()
ns = {"graphml": "http://graphml.graphdrawing.org/xmlns"}
nodes = {}
for node in root.findall("graphml:graph/graphml:node", ns):
node_id = node.get("id")
nodes[node_id] = {
"id": node_id,
"value": len(node.findall("graphml:data", ns)[2].text.split(",")),
}
links = []
for edge in root.findall("graphml:graph/graphml:edge", ns):
source = edge.get("source")
target = edge.get("target")
value = len(edge.findall("graphml:data", ns)[2].text.split(","))
links.append({"source": source, "target": target, "value": value})
return nodes, links
# 构建ECharts所需的JSON数据结构
def build_echarts_data(nodes, links):
return {
"nodes": [
{"name": node["id"], "value": node["value"]} for node in nodes.values()
],
"links": links,
}
# 生成HTML文件
def generate_html(title, data):
html_template = """
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>{{ title }}</title>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/echarts.min.js"></script>
<style>
html, body {
height: 100%;
margin: 0;
padding: 0;
}
#main {
width: 100%;
height: 100vh;
}
</style>
</head>
<body>
<div id="main"></div>
<script type="text/javascript">
var myChart = echarts.init(document.getElementById('main'));
var data = {{ nodes | tojson }};
var links = {{ links | tojson }};
var max_node_value = Math.max(...data.map(node => node.value));
var max_link_value = Math.max(...links.map(link => link.value));
function getNodeStyle(node) {
var color;
var size;
if (node.value > max_node_value*0.8) {
color = 'red';
size = node.value * 10;
} else if (node.value > max_node_value*0.6) {
color = 'orange';
size = node.value * 6;
} else if (node.value > max_node_value*0.4) {
color = 'yellow';
size = node.value * 3;
} else if (node.value > max_node_value*0.2) {
color = 'green';
size = node.value * 2;
} else {
color = 'blue';
size = node.value * 1;
}
return {
symbolSize: size,
itemStyle: {
color: color
}
};
}
function getLinkStyle(link) {
var color;
if (link.value > max_link_value*0.8) {
color = 'red';
} else if (link.value > max_link_value*0.6) {
color = 'orange';
} else if (link.value > max_link_value*0.4) {
color = 'yellow';
} else if (link.value > max_link_value*0.2) {
color = 'green';
} else {
color = 'brown';
}
return {
lineStyle: {
width: link.value * 2,
color: color
}
};
}
var option = {
title: {
text: '{{ title }}'
},
series: [{
type: 'graph',
layout: 'force',
data: data.map(function (node) {
return Object.assign(node, getNodeStyle(node));
}),
links: links.map(function (link) {
return Object.assign(link, getLinkStyle(link));
}),
roam: true,
draggable: true,
label: {
show: true,
fontSize: 12,
fontFamily: 'sans-serif',
formatter: function (node) {
return node.name;
}
},
force: {
repulsion: 100
}
}]
};
myChart.setOption(option);
window.addEventListener('resize', function () {
myChart.resize();
});
</script>
</body>
</html>
"""
template = Template(html_template)
return template.render(title=title, nodes=data["nodes"], links=data["links"])
# 主函数
def main():
# 使用tkinter打开文件对话框
root = Tk()
root.withdraw() # 隐藏主窗口
file_path = filedialog.askopenfilename(
title="选择GraphML文件",
filetypes=[("GraphML files", "*.graphml"), ("All files", "*.*")],
)
if not file_path:
print("没有选择文件")
return
graphml_file = file_path
graphml_file_name = os.path.splitext(os.path.basename(graphml_file))[0]
nodes, links = parse_graphml(graphml_file)
echarts_data = build_echarts_data(nodes, links)
html_content = generate_html(graphml_file_name, echarts_data)
output_file = os.path.join(
os.path.dirname(graphml_file), f"{graphml_file_name}.html"
)
with open(output_file, "w", encoding="utf-8") as f:
f.write(html_content)
print(f"HTML文件生成: {output_file}")
if __name__ == "__main__":
main()
效果展示: