#!/usr/bin/env python3 """ 圐圙文化网络 - Web 可视化应用 使用 Flask + Neo4j + D3.js """ from flask import Flask, render_template, jsonify, request from neo4j import GraphDatabase import json app = Flask(__name__) class KulueNetworkAPI: def __init__(self, uri="bolt://localhost:7687", user="neo4j", password="password"): self.driver = GraphDatabase.driver(uri, auth=(user, password)) def close(self): self.driver.close() def get_network_data(self): """获取完整网络数据用于可视化""" with self.driver.session() as session: # 获取所有节点 nodes_result = session.run(""" MATCH (w:Word) RETURN w.name as name, w.category as category, w.meaning as meaning, w.region as region, w.dynasty as dynasty """) nodes = [] for record in nodes_result: nodes.append({ 'id': record['name'], 'name': record['name'], 'category': record['category'], 'meaning': record['meaning'], 'region': record['region'], 'dynasty': record['dynasty'] }) # 获取所有关系 links_result = session.run(""" MATCH (source:Word)-[r]-(target:Word) RETURN source.name as source, target.name as target, type(r) as type, r.type as subtype """) links = [] processed_pairs = set() for record in links_result: source = record['source'] target = record['target'] # 避免重复的无向边 pair = tuple(sorted([source, target])) if pair not in processed_pairs: processed_pairs.add(pair) links.append({ 'source': source, 'target': target, 'type': record['type'], 'subtype': record['subtype'] }) return {'nodes': nodes, 'links': links} def search_word(self, word_name): """搜索特定词汇的关联""" with self.driver.session() as session: result = session.run(""" MATCH (center:Word {name: $word})-[r]-(connected:Word) RETURN center, r, connected """, word=word_name) data = [] for record in result: center = record['center'] relation = record['r'] connected = record['connected'] data.append({ 'center': dict(center), 'relation': { 'type': relation.type, 'properties': dict(relation) }, 'connected': dict(connected) }) return data def get_categories_stats(self): """获取类别统计""" with self.driver.session() as session: result = session.run(""" MATCH (w:Word) RETURN w.category as category, count(w) as count ORDER BY count DESC """) return [{'category': record['category'], 'count': record['count']} for record in result] def get_sound_shift_paths(self, start_word): """获取音转路径""" with self.driver.session() as session: result = session.run(""" MATCH path = (start:Word {name: $start})-[:SOUND_SHIFT*1..3]-(end:Word) RETURN [node in nodes(path) | node.name] as path_nodes, length(path) as path_length ORDER BY path_length """, start=start_word) return [{'path': record['path_nodes'], 'length': record['path_length']} for record in result] # 创建API实例 kulue_api = KulueNetworkAPI() @app.route('/') def index(): """主页""" return render_template('index.html') @app.route('/api/network') def get_network(): """获取网络数据API""" try: data = kulue_api.get_network_data() return jsonify(data) except Exception as e: return jsonify({'error': str(e)}), 500 @app.route('/api/search/') def search_word(word): """搜索词汇API""" try: data = kulue_api.search_word(word) return jsonify(data) except Exception as e: return jsonify({'error': str(e)}), 500 @app.route('/api/stats/categories') def get_categories(): """获取类别统计API""" try: data = kulue_api.get_categories_stats() return jsonify(data) except Exception as e: return jsonify({'error': str(e)}), 500 @app.route('/api/sound-shift/') def get_sound_shift(word): """获取音转路径API""" try: data = kulue_api.get_sound_shift_paths(word) return jsonify(data) except Exception as e: return jsonify({'error': str(e)}), 500 # HTML 模板 html_template = ''' 圐圙文化网络

圐圙文化网络可视化

''' # 创建模板目录和文件 import os os.makedirs('templates', exist_ok=True) with open('templates/index.html', 'w', encoding='utf-8') as f: f.write(html_template) if __name__ == '__main__': app.run(debug=True, host='0.0.0.0', port=5000)