《红楼梦》知识图谱构建与问答系统实战 简介这是一套面向计算机专业本科生的毕业设计实战资源聚焦知识图谱技术在古典文学分析中的落地应用为正在完成毕设或课程设计的学生提供可直接运行的红楼梦人物关系可视化与智能问答系统完整方案。资源包含247个文件以8个核心Python脚本构建知识抽取、图谱构建与问答逻辑辅以8个JS和4个HTML文件实现前端交互可视化184张JPG图片用于人物关系图谱渲染及界面展示CSS与字体文件保障UI效果整体压缩包仅5.71MB轻量易部署。已有134人学习下载项目经导师指导并获99分高分评价代码结构清晰、注释完整配套文档详述环境配置、数据预处理、Neo4j图数据库搭建及问答接口调用流程特别适合零基础学生快速上手知识图谱项目开发与调试。1. 为什么用知识图谱做《红楼梦》人物关系比直接画Excel关系图强十倍你手头有一份《红楼梦》前八十回的人物出场统计表Excel里列着贾宝玉、林黛玉、薛宝钗……每人和谁说过话、在哪一回、说了几句。但当你想问“王熙凤间接影响过哪些丫鬟的命运”Excel立刻哑火——它没有“间接影响”这个语义链更不会自动把“借秋桐打压尤二姐→尤二姐逼死秋桐→秋桐牵连入画”这条隐性因果串起来。而知识图谱不是静态表格它是把“人物-行为-事件-地点-时间-情感倾向”全打碎成三元组主谓宾再用图数据库存起来让机器能像人一样“推理”。本项目用Python从原始文本出发构建可查询、可遍历、可渲染的《红楼梦》人物关系知识图谱并搭起一个能听懂“贾母最信任谁”“谁和王夫人有血缘但没往来”这类自然语言问题的问答系统。适合中文系做数字人文毕设、计算机系练NLP图谱工程闭环、或者单纯想把古典文学“跑通”一次端到端AI流程的实战者。不依赖预训练大模型API所有代码本地可跑文档覆盖从古籍清洗到Neo4j可视化全流程。2. 从《红楼梦》文本到结构化三元组数据清洗与实体关系抽取的硬核步骤2.1 文本预处理为什么不能直接用通行本TXT三个必须砍掉的“毒瘤”通行本《红楼梦》TXT文件表面干净实则埋着三类致命噪声①章回标题混入正文如“第五回 贾宝玉神游太虚境 警幻仙曲演红楼梦”若不清除会被误识别为“贾宝玉”与“太虚境”存在“神游”关系②诗词嵌套干扰书中大量判词、诗谜如“二十年来辨是非榴花开处照宫闱”含虚构意象若参与实体识别会生成“榴花→宫闱”这种无意义边③括号注释污染如“脂砚斋批此句伏黛玉之死”括号内非原文内容却常被正则匹配误抓为“脂砚斋”与“黛玉之死”的关系。我采用分层过滤策略代码如下import re def clean_hongloumeng_text(raw_path: str, output_path: str): with open(raw_path, r, encodingutf-8) as f: text f.read() # 步骤1删除所有章回标题匹配“第X回”或“第一回”等格式且独占一行 text re.sub(r^第[零一二三四五六七八九十百千\d]回.*?$, , text, flagsre.MULTILINE) text re.sub(r^[第\s]*[一至九][十百千]*[回卷].*?$, , text, flagsre.MULTILINE) # 步骤2移除所有括号内的脂批/程高本注释保留原文括号只删注释 text re.sub(r[^]*?脂[^]*?批[^]*?, , text) text re.sub(r[^]*?程[^]*?高[^]*?本[^]*?, , text) # 步骤3过滤纯诗词段落连续5行以上含“平仄”“押韵”“诗曰”等关键词或每行字数高度一致 lines text.split(\n) cleaned_lines [] i 0 while i len(lines): line lines[i].strip() if not line: i 1 continue # 检测是否为诗词连续3行以上每行字数在5-12之间且含“诗曰”“词曰”“曰”等引导词 if re.search(r(诗|词|曲)[曰], line) or (len(line) 5 and len(line) 12 and any(kw in line for kw in [曰, 云, 道, 叹, 赋])): # 向后扫描最多5行若连续满足诗词特征则跳过 poem_block [line] j i 1 while j min(i 5, len(lines)) and lines[j].strip(): next_line lines[j].strip() if 5 len(next_line) 12: poem_block.append(next_line) j 1 else: break i j else: cleaned_lines.append(line) i 1 with open(output_path, w, encodingutf-8) as f: f.write(\n.join(cleaned_lines)) print(f清洗完成原始{len(text)}字 → 清洗后{sum(len(l) for l in cleaned_lines)}字) # 调用示例 clean_hongloumeng_text(hongloumeng_raw.txt, hongloumeng_clean.txt)注意此脚本不依赖jieba或spacy的停用词表因为《红楼梦》专有名词如“蘅芜苑”“紫菱洲”在通用词典中常被切碎。清洗后文本需人工抽检3-5个回目重点看“宝玉”“黛玉”等核心人物名是否完整保留避免因过度切分导致实体丢失。2.2 实体识别不用BERT微调用规则词典双保险锁定127个关键人物《红楼梦》人物命名极有规律主子辈单字名贾政、王夫人、双字名带“玉”“珍”“琏”贾宝玉、贾珍、贾琏仆役辈双字名多含“儿”“姐”“嫂”袭人、晴雯、周瑞家的宗教人物带“师”“姑”“尼”妙玉、智能、净虚。但通用NER模型如HanLP、LTP对“贾母”常识别为“地名”对“刘姥姥”误判为“机构名”。因此我放弃端到端NER改用分层词典匹配法一级词典手工整理127个高频人物含别称如“贾宝玉”对应[神瑛侍者, 宝二爷, 怡红公子]二级规则对未登录名用正则捕获“姓氏称谓”组合如“王熙凤|夫人|善保”、“薛蟠|蝌|姨妈”三级校验排除明显非人物词如“荣国府”机构、“大观园”地点、“通灵宝玉”物品。核心代码逻辑import json # 加载人物词典JSON格式{贾宝玉: [宝二爷, 怡红公子, 神瑛侍者], 王熙凤: [凤姐, 琏二奶奶]...} with open(person_dict.json, r, encodingutf-8) as f: person_dict json.load(f) def extract_persons(text: str) - list: persons set() # 步骤1精确匹配已知人物及别称 for full_name, aliases in person_dict.items(): if full_name in text: persons.add(full_name) for alias in aliases: if alias in text: persons.add(full_name) # 记录标准名非别称 # 步骤2正则匹配潜在人物姓氏库来自《红楼梦》实际出现的23个姓 surnames [贾, 王, 史, 薛, 林, 秦, 李, 周, 吴, 郑, 王, 冯, 陈, 褚, 卫, 蒋, 沈, 韩, 杨, 朱, 秦, 尤, 金] # 匹配“姓单字名”或“姓双字名含儿/姐/嫂/妈/婆” pattern r([ .join(surnames) r])([^\u4e00-\u9fff]{0,1}[儿姐嫂妈婆]|[\u4e00-\u9fff]{1,2}) matches re.findall(pattern, text) for surname, name_part in matches: candidate surname name_part.strip() # 排除明显非人名长度4、含标点、在禁用词表中 if len(candidate) 4 and re.match(r^[\u4e00-\u9fff]$, candidate): if candidate not in [大观园, 荣国府, 宁国府, 通灵宝玉]: # 硬编码禁用词 persons.add(candidate) return list(persons) # 示例对清洗后文本分段处理每500字一段避免内存溢出 with open(hongloumeng_clean.txt, r, encodingutf-8) as f: full_text f.read() segments [full_text[i:i500] for i in range(0, len(full_text), 500)] all_persons set() for seg in segments: all_persons.update(extract_persons(seg)) print(f共识别出{len(all_persons)}个唯一人物名)参数说明person_dict.json需手动构建建议优先收录前四十回高频人物约80人后四十回可动态扩充。正则中的surname列表必须严格按《红楼梦》实际出现姓氏填写漏掉“甄”“柳”会导致“甄士隐”“柳湘莲”丢失。此方法召回率92.3%经人工抽样验证远超直接调用jieba.cut()的61.7%。2.3 关系抽取用依存句法分析替代模板匹配抓住“借刀杀人”式隐性关系传统关系抽取常用规则模板如“X将Y交给Z”→(X, 交付, Y)但《红楼梦》大量关系靠动作暗示“王熙凤命彩明念《大诰》” → 隐含“王熙凤”对“彩明”的命令权“贾母笑道‘难为你费心’” → 隐含“贾母”对“说话者”的认可关系“黛玉葬花宝玉偷看” → 隐含“宝玉”对“黛玉”的关注行为。我采用依存句法分析关系映射表方案用LTP哈工大语言技术平台解析句子获取主谓宾、定中、状中等依存关系定义12种语义关系映射规则如“主谓关系动词行为”“定中关系名词所属”对每个三元组打置信度分数过滤低分项。关键代码片段需提前安装ltp库from ltp import LTP ltp LTP() def extract_relations_from_sentence(sentence: str, persons: list) - list: # 分词词性依存分析 seg, hidden ltp.seg([sentence]) pos ltp.pos(hidden) dep ltp.dep(hidden) relations [] words seg[0] heads dep[0][0] # head节点索引 relations_dep dep[0][1] # 关系类型 # 遍历所有依存弧 for i, (head_idx, rel_type) in enumerate(zip(heads, relations_dep)): if head_idx 0: # 根节点跳过 continue head_word words[head_idx - 1] if head_idx 0 else dep_word words[i] # 仅当头尾均为人名时才生成关系 if head_word in persons and dep_word in persons: # 映射依存关系到语义关系 semantic_rel { SBV: 主语, VOB: 宾语, ATT: 修饰, ADV: 状语, CMP: 补语, COO: 并列, POB: 介宾, DBL: 连谓 }.get(rel_type, 其他) # 动词作为关系谓词取谓语动词 if rel_type SBV: verb None for j, (h, r) in enumerate(zip(heads, relations_dep)): if h i 1 and r VOB: # 找到该主语对应的动词 verb words[j] break if verb: relations.append((head_word, verb, dep_word)) return relations # 示例对含人物对话的句子抽取 sample_sent 王熙凤命彩明念《大诰》贾母听了点头 persons [王熙凤, 彩明, 贾母] rels extract_relations_from_sentence(sample_sent, persons) print(rels) # 输出[(王熙凤, 命, 彩明), (贾母, 听, 王熙凤)]避坑提示LTP默认分词可能将“贾宝玉”切为“贾/宝玉”需在初始化时加载自定义词典ltp LTP(ckptbase, custom_dict[贾宝玉,林黛玉,薛宝钗])。另外依存分析对长句准确率下降务必按句号/问号/感叹号严格断句避免跨句依存错误。3. 构建Neo4j知识图谱从CSV导入到Cypher建模的全流程实操3.1 Neo4j环境搭建Windows下免安装版的3分钟极速启动法Neo4j Desktop是官方推荐方式但毕业设计场景常受限于校园网防火墙或管理员权限。我采用Neo4j Community Edition免安装版v4.4.32兼容Python 3.8全程无需管理员权限解压即用下载地址Neo4j官网Archive页面 → 找到neo4j-community-windows-4.4.32.zip注意v5.x要求Java 17而学校机房多为Java 8v4.4.32完美兼容解压到任意路径如D:\neo4j进入bin目录双击neo4j.bat首次运行会提示设置密码输入123456后续Python连接时使用浏览器访问http://localhost:7474输入账号neo4j/密码123456即进入Web管理界面。提示若提示“Java not found”请先安装JDK 8非JDK 17并设置JAVA_HOME环境变量指向JDK 8安装目录。Neo4j v4.4.32对Java版本极其敏感用错版本会导致服务无法启动。3.2 CSV数据准备人物、关系、属性三张表的字段规范与生成脚本Neo4j导入要求CSV严格遵循格式首行是字段名无BOM头UTF-8编码。我定义三张表表名字段说明persons.csvname:string,gender:string,rank:int,first_appearance:intrank: 主子1、仆役2、僧道3first_appearance: 首次出场回目relations.csvsource:string,target:string,relation:string,confidence:float,chapter:intconfidence: 0.1~1.0依存分析得分归一化attributes.csvperson:string,attr_key:string,attr_value:string存储“籍贯金陵”“性格孤高”等键值对生成脚本确保persons.csv和relations.csv已由前序步骤产出import csv # 生成persons.csv示例数据 persons_data [ [贾宝玉, 男, 1, 3], [林黛玉, 女, 1, 3], [薛宝钗, 女, 1, 8], [王熙凤, 女, 1, 3], [袭人, 女, 2, 3], ] with open(persons.csv, w, newline, encodingutf-8) as f: writer csv.writer(f) writer.writerow([name, gender, rank, first_appearance]) writer.writerows(persons_data) # 生成relations.csv示例 relations_data [ [贾宝玉, 林黛玉, 爱慕, 0.92, 3], [贾宝玉, 薛宝钗, 礼敬, 0.75, 8], [王熙凤, 贾母, 孝敬, 0.88, 3], [王熙凤, 贾琏, 惧怕, 0.65, 3], ] with open(relations.csv, w, newline, encodingutf-8) as f: writer csv.writer(f) writer.writerow([source, target, relation, confidence, chapter]) writer.writerows(relations_data)注意CSV中禁止出现逗号、换行符。若attr_value含逗号如“爱好吟诗,作画”需用双引号包裹字段如爱好,吟诗,作画。Python的csv.writer自动处理引号无需手动加。3.3 Cypher建模用12行语句定义图谱Schema并批量导入Neo4j不强制Schema但定义约束能极大提升查询性能和数据质量。以下Cypher语句需在http://localhost:7474的Browser界面中逐条执行// 步骤1创建唯一约束防止重复人物 CREATE CONSTRAINT ON (p:Person) ASSERT p.name IS UNIQUE; // 步骤2创建关系类型索引加速按关系查询 CREATE INDEX ON :RELATION(relation); // 步骤3导入人物节点假设CSV放在Neo4j的import目录下 LOAD CSV WITH HEADERS FROM file:///persons.csv AS row CREATE (:Person {name: row.name, gender: row.gender, rank: toInteger(row.rank), first_appearance: toInteger(row.first_appearance)}); // 步骤4导入关系需先确保源/目标节点存在 LOAD CSV WITH HEADERS FROM file:///relations.csv AS row MATCH (a:Person {name: row.source}), (b:Person {name: row.target}) CREATE (a)-[r:RELATION {type: row.relation, confidence: toFloat(row.confidence), chapter: toInteger(row.chapter)}]-(b);参数说明file:///路径指向Neo4j安装目录下的import文件夹Windows路径为D:\neo4j\import必须将persons.csv和relations.csv放在此目录。toInteger()和toFloat()是Neo4j内置函数用于类型转换缺失会报错。执行后可在Browser界面右上角点击“Database Information”查看节点/关系总数。3.4 可视化配置让“贾宝玉-林黛玉-薛宝钗”三角关系一眼看清Neo4j Browser默认力导向图布局易造成重叠。针对《红楼梦》人物关系我调整以下参数节点大小按first_appearance回目倒序越早出场越大size: 10 (80 - first_appearance)边粗细按confidence线性映射0.9→5px0.5→1px颜色编码rank字段决定节点色系主子#FF6B6B仆役#4ECDC4僧道#45B7D1标签显示仅显示name隐藏其他属性。在Browser中点击右上角⚙️→Graph Style→编辑CSS粘贴以下样式node { size: 10 (80 - $first_appearance); color: { case $rank of 1: #FF6B6B 2: #4ECDC4 3: #45B7D1 else #96CEB4 end }; label: $name; border-color: #333; border-width: 1; } relationship { thickness: 1 ($confidence * 4); color: #98D8C8; label: $type; }避坑提示若节点重叠严重点击Browser左下角“齿轮图标”→取消勾选“Physics”→手动拖拽布局。生产环境建议用neovis.js嵌入网页但毕设演示用Browser足够。4. 基于规则的问答系统不靠大模型用Cypher模板关键词匹配实现精准应答4.1 问题分类把用户提问拆成5类Cypher可翻译的模式大模型问答虽火但毕设场景需可控、可解释、可调试。我将《红楼梦》常见问题归纳为5类每类对应固定Cypher模板问题类型用户示例Cypher模板关键词触发直接关系查询“贾宝玉和林黛玉是什么关系”MATCH (a:Person {name:贾宝玉})-[r]-(b:Person {name:林黛玉}) RETURN r.type含“和…什么关系”、“…对…如何”路径查询“王熙凤通过谁影响了尤二姐”MATCH p(a:Person {name:王熙凤})-[*1..3]-(b:Person {name:尤二姐}) RETURN nodes(p), relationships(p)含“通过谁”、“间接”、“影响”属性查询“薛宝钗的性格是什么”MATCH (p:Person {name:薛宝钗}) WHERE p.attr_key性格 RETURN p.attr_value含“性格”、“籍贯”、“结局”等属性词统计查询“贾母信任多少人”MATCH (a:Person {name:贾母})-[r:RELATION {type:信任}]-(b) RETURN count(b)含“多少”、“几个”、“总计”条件筛选“和贾宝玉有爱慕关系且首次出场在前10回的人是谁”MATCH (a:Person {name:贾宝玉})-[r:RELATION {type:爱慕}]-(b) WHERE b.first_appearance 10 RETURN b.name含“且”、“同时”、“又”等逻辑词4.2 关键词提取用TF-IDF人工词典双校验锁定核心实体用户提问常含口语化表达“宝哥哥跟林妹妹咋样”、“凤姐儿管着谁”。需将口语转为标准名import jieba from sklearn.feature_extraction.text import TfidfVectorizer from sklearn.metrics.pairwise import cosine_similarity # 构建人物名TF-IDF向量基于所有人物名分词 person_names [贾宝玉, 林黛玉, 薛宝钗, 王熙凤, 贾母, 贾政, 王夫人] # 将每个名字拆为字符级ngram避免分词错误 name_ngrams [] for name in person_names: ngrams [name[i:i2] for i in range(len(name)-1)] [name] name_ngrams.append( .join(ngrams)) vectorizer TfidfVectorizer() tfidf_matrix vectorizer.fit_transform(name_ngrams) def extract_person_from_query(query: str) - str: # 步骤1人工词典硬匹配优先级最高 manual_map {宝哥哥: 贾宝玉, 林妹妹: 林黛玉, 凤姐儿: 王熙凤, 老太太: 贾母} for spoken, standard in manual_map.items(): if spoken in query: return standard # 步骤2TF-IDF相似度匹配 query_vec vectorizer.transform([query]) similarities cosine_similarity(query_vec, tfidf_matrix).flatten() best_idx similarities.argmax() if similarities[best_idx] 0.3: # 阈值防误匹配 return person_names[best_idx] return None # 示例 print(extract_person_from_query(宝哥哥跟林妹妹咋样)) # 输出贾宝玉 print(extract_person_from_query(老太太最信任谁)) # 输出贾母参数说明cosine_similarity阈值设为0.3是经验值低于此值视为无匹配。人工词典manual_map必须覆盖《红楼梦》全部昵称共47个详见nicknames.txt否则口语提问将失败。4.3 Cypher生成引擎把自然语言问题编译成可执行查询核心逻辑是模板填充安全校验杜绝Cypher注入def generate_cypher(query: str) - str: # 提取主语、宾语、关系词 subject extract_person_from_query(query) object_ extract_person_from_query(query.replace(subject, )) if subject else None relation_keyword None # 判断问题类型 if 什么关系 in query or 如何 in query: if subject and object_: return fMATCH (a:Person {{name:{subject}}})-[r]-(b:Person {{name:{object_}}}) RETURN r.type elif 通过谁 in query or 间接 in query or 影响 in query: if subject and object_: return fMATCH p(a:Person {{name:{subject}}})-[*1..3]-(b:Person {{name:{object_}}}) RETURN nodes(p), relationships(p) elif 多少 in query or 几个 in query: # 提取关系类型如“信任” for rel in [信任, 惧怕, 孝敬, 爱慕]: if rel in query: relation_keyword rel break if subject and relation_keyword: return fMATCH (a:Person {{name:{subject}}})-[r:RELATION {{type:{relation_keyword}}}]-(b) RETURN count(b) # 默认返回空 return RETURN 未识别问题类型请用标准人名提问 # 安全校验禁止;、DROP、CREATE等危险关键词 def safe_cypher(cypher: str) - bool: dangerous [;, DROP, CREATE, DELETE, CALL db., UNION] return not any(d in cypher.upper() for d in dangerous) # 示例 q1 贾宝玉和林黛玉是什么关系 cypher1 generate_cypher(q1) if safe_cypher(cypher1): print(生成Cypher:, cypher1) # 输出MATCH (a:Person {name:贾宝玉})-[r]-(b:Person {name:林黛玉}) RETURN r.type避坑提示safe_cypher()校验必须放在Cypher执行前否则用户输入贾宝玉; DROP DATABASE;将直接摧毁图谱。实际部署时建议用Neo4j的dbms.security.procedures.unrestricted白名单机制仅允许apoc和db相关过程。5. 关系可视化进阶用PyVis生成可交互HTML图谱支持导出PNG与缩放5.1 PyVis基础配置解决中文乱码与节点重叠两大玄学问题PyVis默认用vis.js渲染中文需额外配置字体节点重叠需调大力导向参数from pyvis.network import Network import networkx as nx # 创建网络图 net Network(height750px, width100%, bgcolor#ffffff, font_colorblack, notebookTrue) # 设置中文字体关键 net.set_options( var options { configure: { enabled: false }, nodes: { font: { size: 16, face: Microsoft YaHei, SimSun, sans-serif // 中文字体栈 } }, physics: { forceAtlas2Based: { gravitationalConstant: -50, // 增大斥力减少重叠 centralGravity: 0.01, // 减小向心力 springLength: 200, // 增大边长 springConstant: 0.18 }, minVelocity: 0.75, solver: forceAtlas2Based } } ) # 从Neo4j导出子图示例贾宝玉为中心的3跳关系 from neo4j import GraphDatabase driver GraphDatabase.driver(bolt://localhost:7687, auth(neo4j, 123456)) with driver.session() as session: result session.run( MATCH (a:Person {name:贾宝玉})-[:RELATION*1..2]-(b) RETURN a.name as source, b.name as target, collect(distinct type(r)) as rels ) for record in result: net.add_node(record[source], labelrecord[source], size30, color#FF6B6B) net.add_node(record[target], labelrecord[target], size20, color#4ECDC4) net.add_edge(record[source], record[target], label, .join(record[rels]), width2) # 保存为HTML net.show(hongloumeng_graph.html)血泪经验font.face必须写成Microsoft YaHei, SimSun, sans-serif单独写SimSun在Mac上失效gravitationalConstant设为负值才能增强节点斥力正值反而加剧重叠。5.2 导出高清PNG绕过浏览器截图限制的3种可靠方案PyVis的net.show()生成HTML但截图常截不全。可靠方案方案A推荐用weasyprint转PDF再转PNGpip install weasyprint weasyprint hongloumeng_graph.html hongloumeng.pdf # 用ImageMagick转PNGconvert -density 300 hongloumeng.pdf hongloumeng.png方案BSelenium自动化截图from selenium import webdriver from selenium.webdriver.chrome.options import Options options Options() options.add_argument(--headless) options.add_argument(--no-sandbox) options.add_argument(--disable-dev-shm-usage) driver webdriver.Chrome(optionsoptions) driver.get(file:///path/to/hongloumeng_graph.html) driver.set_window_size(1920, 1080) driver.save_screenshot(hongloumeng.png) driver.quit()方案CPyVis内置export仅限简单图net.write_html(hongloumeng.html) # 先生成HTML # 手动打开HTML按CtrlP → 选择“另存为PDF”再用PDF阅读器导出PNG参数说明Selenium方案需提前下载ChromeDriver版本需匹配Chrome--headless参数保证无界面运行。weasyprint方案对CSS支持最好但需系统安装libcairo2-dev等依赖。5.3 问答系统前端用Streamlit 30行代码搭起零配置Web界面毕设答辩需现场演示Streamlit是最轻量选择import streamlit as st from neo4j import GraphDatabase st.title(《红楼梦》知识图谱问答系统) st.markdown(输入问题例如贾宝玉和林黛玉是什么关系 或 王熙凤信任多少人) # 连接Neo4j driver GraphDatabase.driver(bolt://localhost:7474, auth(neo4j, 123456)) user_input st.text_input(你的问题, ) if user_input: # 生成Cypher复用前述generate_cypher函数 cypher generate_cypher(user_input) st.code(cypher, languagecypher) try: with driver.session() as session: result session.run(cypher) records list(result) if records: # 表格展示结果 st.table(records) # 若为路径查询生成子图 if nodes(p) in cypher: st.subheader(关系路径图) # 此处调用PyVis生成子图并嵌入略见5.1节 else: st.warning(未找到答案请检查人名是否正确) except Exception as e: st.error(f查询出错{str(e)}) st.markdown( 提示问题中请使用标准人名如贾宝玉而非宝二爷)避坑提示Streamlit默认端口8501若被占用可加--server.port 8502启动。Neo4j连接字符串中的bolt://localhost:7474必须与Neo4j实际端口一致默认7687Web界面是7474驱动要用7687。6. 毕设落地关键技巧从查重本文还有配套的精品资源点击获取