简介:这份资源围绕《红楼梦》知识图谱的构建与展示展开,面向希望入门知识图谱、图数据库与Python实战的学生和开发者。它解决的是如何将人物、家族、事件等文本信息转化为结构化图数据,并借助Neo4j完成存储、查询与可视化呈现的问题,适合作为课程设计、毕业项目或自学练手素材。压缩包共7个文件,约1.62MB,包含csv三元组数据、Python脚本、Neo4j数据库备份、图谱展示图片及说明文档,覆盖从数据组织到图库导入再到结果呈现的完整链路。目前已有160人学习下载。读者可借助三元组文件理解实体与关系的组织方式,通过Python脚本完成数据抽取与导入,利用数据库备份快速还原图谱环境,并结合展示图与说明文档核对节点、边及查询效果,从而掌握知识图谱从数据到可视化的基本流程。
1. 红楼梦知识图谱展示与 Neo4j:从文本到图数据库的落地路径
读《红楼梦》时,人物关系复杂到让人抓狂——贾、史、王、薛四大家族盘根错节,光是有名有姓的角色就超过四百个。如果只用关系型数据库存人物和事件,多跳查询会写得又长又慢,比如“找出与贾宝玉有间接关系且出现在同一回目中的所有女性角色”,SQL 写起来得嵌套好几层。知识图谱用节点和边直接表达“谁认识谁”“谁住在哪”“谁和谁有血缘”,天然适合这种场景。这份资源把红楼梦文本整理成结构化数据,导入 Neo4j 图数据库,再配一套前端展示页面,让你能直观看到人物关系网络。适合做课程设计、毕设,或者想练手知识图谱构建的 Python 开发者。下面从数据准备、Neo4j 安装配置、图谱构建到前端展示,一步步拆开讲。
2. 数据准备与 Neo4j 环境搭建:从 CSV 到图数据库
2.1 红楼梦人物关系数据的组织方式
这份资源的数据层通常包含三类 CSV 文件:节点文件(人物、地点、事件)、关系文件(亲属、主仆、社交)、属性文件(人物别号、判词、回目)。常见做法是把人物节点存成person.csv,字段包括id、name、gender、identity、family;关系存成relation.csv,字段包括start_id、end_id、type、weight。weight表示关系亲密度,比如宝玉和黛玉的“知己”关系权重设为 5,宝玉和袭人的“主仆”关系权重设为 3。这样后续在 Neo4j 里可以用weight做路径排序,找出“最强关系链”。
我一般会先用 Python 的pandas做一轮清洗,把重复人物合并,比如“宝玉”和“贾宝玉”统一成同一个id。清洗脚本如下:
import pandas as pd # 读取原始人物列表 df = pd.read_csv('raw_person.csv', encoding='utf-8') # 统一名称:去掉“贾”前缀的别名映射 name_map = { '宝玉': '贾宝玉', '黛玉': '林黛玉', '宝钗': '薛宝钗', '凤姐': '王熙凤' } df['name'] = df['name'].replace(name_map) # 生成唯一 id,用拼音首字母加序号 df['id'] = df['name'].apply(lambda x: 'p_' + str(abs(hash(x)) % 10000)) # 去重,保留第一次出现的记录 df = df.drop_duplicates(subset=['name'], keep='first') df.to_csv('person_clean.csv', index=False, encoding='utf-8') print(f'清洗后人物数量:{len(df)}')这段代码做了三件事:别名归一、生成稳定id、去重。hash取模是为了让id短一点,但注意hash在不同 Python 进程里可能不一致,生产环境建议用uuid或自增序号。清洗完的人物表大概 400 行左右,关系表大概 800 行,数据量不大,Neo4j 社区版完全够用。
2.2 Neo4j 安装与配置:社区版够用,但内存要调
Neo4j 有桌面版、社区版、企业版。做红楼梦知识图谱,社区版足够,因为数据量小,不需要集群和高级权限。Windows 和 macOS 都能装,常见做法是下载压缩包解压,然后改配置文件。关键参数在conf/neo4j.conf里:
# 允许远程访问,默认只监听 localhost dbms.default_listen_address=0.0.0.0 # Bolt 协议端口,Python 驱动默认连 7687 dbms.connector.bolt.listen_address=:7687 # HTTP 端口,浏览器访问 7474 dbms.connector.http.listen_address=:7474 # 堆内存,根据机器调整,4G 内存机器给 1G 左右 dbms.memory.heap.initial_size=1G dbms.memory.heap.max_size=1G # 页面缓存,数据小可以设 512M dbms.memory.pagecache.size=512M改完配置后,Linux/macOS 用bin/neo4j start启动,Windows 用bin\neo4j.bat start。启动后浏览器打开http://localhost:7474,默认用户名和密码都是neo4j,第一次登录会强制改密码。如果启动报错“找不到数据库引擎启动句柄”,八成是 Java 版本不对——Neo4j 4.x 需要 Java 11,5.x 需要 Java 17。用java -version确认一下,别在这上面翻车。
提示:社区版不支持多数据库,默认只有一个
neo4j库。导入数据前先清空旧数据,避免节点重复。
2.3 用 Cypher 批量导入 CSV 数据
Neo4j 导入 CSV 有两种方式:LOAD CSV和neo4j-admin import。数据量小用LOAD CSV更灵活,可以边导入边建关系。先把 CSV 文件放到 Neo4j 安装目录的import文件夹下,然后执行:
// 导入人物节点 LOAD CSV WITH HEADERS FROM 'file:///person_clean.csv' AS row CREATE (p:Person { id: row.id, name: row.name, gender: row.gender, identity: row.identity, family: row.family }); // 建立索引,加速后续查询 CREATE INDEX person_id_index IF NOT EXISTS FOR (p:Person) ON (p.id); // 导入关系 LOAD CSV WITH HEADERS FROM 'file:///relation_clean.csv' AS row MATCH (a:Person {id: row.start_id}) MATCH (b:Person {id: row.end_id}) CREATE (a)-[:RELATION { type: row.type, weight: toInteger(row.weight) }]->(b);LOAD CSV默认从import目录读文件,路径写file:///开头。CREATE会重复创建节点,如果反复执行会生成重复数据,建议先用MATCH检查再决定用CREATE还是MERGE。MERGE会先查再建,速度慢一点但安全。关系导入时用了toInteger转换,因为 CSV 读进来默认是字符串,不转会变成字符串类型的weight,后续排序会出错。
3. 知识图谱构建:实体抽取与关系建模的实操细节
3.1 从回目文本中抽取人物共现关系
红楼梦一百二十回,每回出场人物不同。如果两个人出现在同一回,可以认为他们之间有“共现关系”。这种关系虽然粗糙,但能快速构建一个基础图谱。用 Python 的jieba分词加人物词典匹配,可以统计每回的人物列表:
import jieba import pandas as pd from collections import defaultdict # 加载人物词典,确保人名不被切碎 jieba.load_userdict('person_dict.txt') # 读取回目文本,每回一个 txt 文件 co_occur = defaultdict(int) for chapter in range(1, 121): with open(f'chapters/{chapter}.txt', 'r', encoding='utf-8') as f: text = f.read() # 分词并过滤出人物名 words = jieba.lcut(text) persons = set([w for w in words if w in person_set]) # 统计两两共现 person_list = list(persons) for i in range(len(person_list)): for j in range(i+1, len(person_list)): pair = tuple(sorted([person_list[i], person_list[j]])) co_occur[pair] += 1 # 输出共现关系,过滤掉共现次数小于 2 的噪声 with open('co_occur.csv', 'w', encoding='utf-8') as f: f.write('start_id,end_id,weight\n') for (a, b), w in co_occur.items(): if w >= 2: f.write(f'{a},{b},{w}\n')jieba.load_userdict是关键,不加的话“贾宝玉”会被切成“贾”、“宝玉”、“玉”三个词。person_set是从清洗后的人物表里读出来的集合。共现次数小于 2 的边建议过滤掉,否则图谱会太密,前端展示时像一团毛线。这个脚本跑完大概生成 2000 多条共现边,配合之前的人物关系边,图谱就有层次了。
3.2 用 Neo4j 查询验证图谱结构
数据导入后,先用几条 Cypher 验证图谱是否合理。比如查贾宝玉的直接关系:
MATCH (p:Person {name: '贾宝玉'})-[r:RELATION]->(other) RETURN p.name, r.type, r.weight, other.name ORDER BY r.weight DESC LIMIT 20;这条查询会返回宝玉的所有出边关系,按权重降序。如果发现“贾宝玉 -> 贾宝玉”这种自环,说明关系表里有脏数据,需要回 CSV 里检查start_id和end_id是否相等。再查一个多跳路径:
MATCH path = (a:Person {name: '贾宝玉'})-[*1..3]-(b:Person {name: '林黛玉'}) RETURN path LIMIT 5;[*1..3]表示 1 到 3 跳,不限方向。这条查询能找出宝玉和黛玉之间的所有间接路径,比如“宝玉-袭人-黛玉”或者“宝玉-宝钗-黛玉”。如果路径太多,可以加WHERE限制关系类型,比如只走RELATION边。注意*1..3在数据量大时会很慢,红楼梦数据小无所谓,但工业场景下要控制跳数,一般不超过 4 跳。
3.3 图谱展示的前端选型:D3.js 还是 ECharts
前端展示知识图谱,常见方案有 D3.js、ECharts、Vis.js、Cytoscape.js。D3.js 最灵活但学习曲线陡,ECharts 的graph类型开箱即用,适合快速出效果。这份资源如果带前端页面,大概率用的是 ECharts 或 D3.js。我一般会选 ECharts,因为配置简单,支持力导向布局、拖拽、缩放,还能自定义节点颜色和大小。一个最小示例:
// 从 Neo4j 后端接口获取节点和边数据 fetch('/api/graph') .then(res => res.json()) .then(data => { const chart = echarts.init(document.getElementById('graph')); const option = { series: [{ type: 'graph', layout: 'force', data: data.nodes.map(n => ({ name: n.name, symbolSize: n.weight * 5, // 权重越大节点越大 category: n.family })), links: data.edges.map(e => ({ source: e.start, target: e.end, value: e.weight })), force: { repulsion: 300, // 斥力,越大节点越分散 edgeLength: 150 // 边长 }, roam: true, label: { show: true } }] }; chart.setOption(option); });repulsion和edgeLength是两个关键参数。repulsion太小节点会挤在一起,太大又散得看不见;edgeLength控制边的长度,一般 100 到 200 之间。symbolSize用权重映射,能让重要人物更显眼。后端接口可以用 Flask 或 FastAPI 写,从 Neo4j 查数据转成 JSON 返回。注意跨域问题,前端和后端不同端口时要加 CORS 头。
4. 避坑与常见问题排查
4.1 导入 CSV 时报“Unable to load CSV”
现象:执行LOAD CSV时提示文件找不到或权限不足。原因:Neo4j 只允许从import目录读文件,而且路径要用file:///开头。如果 CSV 放在其他目录,要么复制到import下,要么改conf/neo4j.conf里的dbms.directories.import参数。解决:把 CSV 放到import目录,确认文件编码是 UTF-8 无 BOM,Windows 下用记事本另存为时选 UTF-8。
4.2 中文乱码或人物名显示为问号
现象:Neo4j 浏览器里看到的人物名是乱码。原因:CSV 文件编码不是 UTF-8,或者 Neo4j 启动时 JVM 编码不对。解决:CSV 统一用 UTF-8 保存;启动脚本里加-Dfile.encoding=UTF-8,Linux 下在neo4j.conf里加dbms.jvm.additional=-Dfile.encoding=UTF-8。另外,LOAD CSV时可以指定FIELDTERMINATOR,但中文逗号不行,必须用英文逗号。
4.3 关系导入后查询不到路径
现象:节点都导入了,但MATCH path = (a)-[*1..3]-(b)返回空。原因:关系导入时MATCH没匹配到节点,导致关系没建上。常见情况是start_id和end_id在人物表里不存在,或者大小写不一致。解决:先跑MATCH (p:Person) RETURN count(p)确认节点数,再跑MATCH ()-[r:RELATION]->() RETURN count(r)确认关系数。如果关系数为 0,检查 CSV 里的id是否和人物表的id完全一致,包括前缀。
4.4 Neo4j 启动后内存占用过高
现象:启动 Neo4j 后机器变卡,或者报“OutOfMemoryError”。原因:默认堆内存设置偏大,或者页面缓存设得太大。解决:在neo4j.conf里把dbms.memory.heap.max_size调到 1G 或 2G,dbms.memory.pagecache.size调到 512M。如果数据量确实大,再往上加。另外,社区版不支持动态调整内存,改完必须重启。
4.5 前端图谱节点重叠严重
现象:ECharts 力导向图里节点挤成一团,看不清标签。原因:repulsion太小,或者节点太多。解决:把repulsion调到 500 以上,edgeLength调到 200 左右。如果节点超过 200 个,建议做筛选,比如只显示权重前 100 的关系,或者按家族分色显示。ECharts 还支持draggable和roam,让用户手动拖拽调整。
5. 进阶技巧:用 APOC 做路径分析和图谱导出
5.1 安装 APOC 插件扩展 Cypher 能力
Neo4j 社区版自带的功能有限,APOC(Awesome Procedures on Cypher)提供了大量实用过程,比如路径展开、节点相似度、图算法。安装方法:从 GitHub 下载对应版本的 APOC jar 包,放到plugins目录,然后在neo4j.conf里加一行:
dbms.security.procedures.unrestricted=apoc.*重启后跑RETURN apoc.version()验证。APOC 装好后,可以用apoc.path.expandConfig做更灵活的路径查询:
MATCH (start:Person {name: '贾宝玉'}) CALL apoc.path.expandConfig(start, { relationshipFilter: 'RELATION', minLevel: 1, maxLevel: 3, limit: 100 }) YIELD path RETURN path;relationshipFilter可以指定只走某种关系,minLevel和maxLevel控制跳数,limit防止返回过多结果。这比原生[*1..3]更可控,尤其在图谱边很多的时候。
5.2 用 Neo4j 图算法找核心人物
Neo4j 的 Graph Data Science 库(GDS)可以做 PageRank、社区发现、中心度计算。红楼梦里谁是最核心的人物?用 PageRank 跑一下就知道:
// 先投影一个子图 CALL gds.graph.project( 'hongloumeng', 'Person', 'RELATION' ); // 跑 PageRank CALL gds.pageRank.stream('hongloumeng') YIELD nodeId, score RETURN gds.util.asNode(nodeId).name AS name, score ORDER BY score DESC LIMIT 10;结果大概率是贾宝玉、王熙凤、林黛玉、薛宝钗排前面。score越高说明人物在图中的影响力越大。这个结果可以反哺前端,把高分节点显示得更大。GDS 库需要单独安装,社区版支持但有限制,数据量小没问题。
5.3 图谱导出与静态展示
如果不想每次开 Neo4j 服务,可以把图谱导出成 JSON 或 GraphML,前端直接读静态文件。用 APOC 导出:
CALL apoc.export.json.all('hongloumeng.json', {useTypes: true});导出的 JSON 包含所有节点和关系,前端用 D3.js 或 ECharts 加载即可。注意导出的文件在 Neo4j 的import目录下。如果要做成静态网站,可以把 JSON 和 HTML 一起打包,部署到任意静态服务器。我习惯在导出前先跑一遍apoc.export.json.query,只导出需要的子图,避免文件太大。
从那以后我每次做知识图谱项目,都强制走一遍“清洗-导入-验证-导出”的流程,尤其是验证环节,不跑几条多跳查询心里不踏实。希望帮到你。
本文还有配套的精品资源,点击获取