Python实战编写小说解析器自动提取素材供水墨江南模型再创作最近在玩一些AI绘画和故事生成模型比如水墨江南这种能生成极简中式风格的模型感觉特别有意思。但有时候直接给一个简单的描述比如“一个侠客在竹林里”生成的内容虽然好看但总觉得少了点故事感和深度。我就想能不能先让AI“读懂”一个完整的故事比如一篇网络小说然后让它基于这个故事里的人物和场景去创作一些新的画面或者番外故事呢这样一来生成的图像或文字就不再是孤立的场景而是有背景、有情感、有前因后果的“故事新编”。这个想法听起来复杂其实拆解开来核心就是两步第一步用Python写个工具能自动从小说文本里把人物、地点、关键情节这些“素材”给提取出来第二步把这些结构化的素材整理成清晰的指令喂给像水墨江南这样的AI模型引导它进行二次创作。今天我就来分享一下怎么动手实现这个“小说解析器”并把它和水墨江南模型的创作流程结合起来。整个过程不需要高深的算法知识用一些现成的Python库就能搞定特别适合喜欢折腾AI应用的朋友。1. 为什么需要小说解析器你可能觉得直接把小说全文复制粘贴给AI不就行了吗理论上可以但实际效果往往不尽如人意。现在的AI大模型尤其是专注于图像生成或风格化创作的模型它们的“注意力”是有限的。你给它一整部上百万字的小说它很难精准地抓住你真正想让它描绘的那个核心人物、那个特定场景或者那段关键情节。结果可能就是生成的内容过于泛泛或者偏离主题。小说解析器的作用就是充当一个“信息提炼师”。它像是一个细心的读者帮你快速浏览完整个故事然后交给你一份清晰的“读书笔记”人物档案故事里有哪些主要角色他们的名字、身份、关系是什么例如主角-李逍遥身份-客栈店小二与赵灵儿是情侣关系场景地图故事发生在哪些典型的地点例如余杭镇、仙灵岛、锁妖塔情节梗概整个故事的主线是什么某个章节的核心冲突又是什么例如第一章李逍遥在客栈邂逅神秘少女赵灵儿为其前往仙灵岛求药。有了这份结构化的“素材库”你再给AI模型下指令时就可以非常精确了。比如你可以对水墨江南模型说“请根据‘李逍遥’和‘仙灵岛’这两个要素生成一幅充满邂逅与神秘感的极简中式场景图。” 这样的指令比单纯说“画一个岛和一个人”要有指向性得多AI生成的内容也会更贴合原作的意境。简单来说解析器把“大海”般的小说文本过滤成了AI模型更容易吸收和发挥的“纯净水”让后续的创作事半功倍。2. 构建小说解析器的核心思路写这个解析器我们不追求像专业NLP论文里那样做到百分之百的准确而是追求“可用”和“有趣”。我们的目标是提取出足够多、足够有代表性的素材来激发AI的创作灵感。整个流程可以分成几个关键步骤我们用一张图来直观感受一下flowchart TD A[输入: 原始小说文本] -- B(文本预处理br清洗与分段) B -- C{核心信息提取} C -- D[人物识别] C -- E[场景/地点识别] C -- F[关键情节摘要] D -- G[结构化整理] E -- G F -- G G -- H[输出: JSON结构化素材库] H -- I[引导AI模型br如“水墨江南”] I -- J[生成新的图像或故事]下面我们来拆解每一步具体怎么做。2.1 第一步获取与预处理文本首先你得有小说文本。可以从某些提供文本下载的网站获取请注意版权或者手动复制粘贴。假设我们已经有了一个novel.txt文件。预处理的目标是把乱七八糟的文本整理干净。常见的“噪音”包括网页残留的HTML标签、多余的空格和换行符、无关的广告文字等。import re def preprocess_text(text): 清洗小说文本。 # 移除常见的HTML标签如果有的话 text re.sub(r‘[^]‘, ‘ ‘, text) # 将多个连续的空格、换行、制表符替换为单个空格 text re.sub(r‘\s‘, ‘ ‘, text) # 这里可以添加更多针对特定来源的清洗规则 # 例如移除“本章说”、“求订阅”等特定平台水印 text re.sub(r‘本章说.*?‘, ‘ ‘, text) return text.strip() # 读取小说文件 with open(‘novel.txt‘, ‘r‘, encoding‘utf-8‘) as f: raw_text f.read() cleaned_text preprocess_text(raw_text) print(f文本清理完成长度从 {len(raw_text)} 字符减少到 {len(cleaned_text)} 字符。)预处理后我们得到了干净的、连续的文本。接下来为了后续分析章节我们可以用一个简单的方法进行初步分章——寻找类似“第一章”、“第1章”或“##”这样的模式。def split_into_chapters(text): 一个简单的基于正则表达式的分章函数。 实际小说格式复杂这里只是一个基础示例。 # 匹配“第X章”或“第XX章”等模式 chapter_pattern r‘(第[零一二三四五六七八九十百千万\d]章[^\n]*)‘ chapters re.split(chapter_pattern, text) # re.split会保留分隔符所以奇数索引是章节标题偶数索引是章节内容 chapter_list [] for i in range(1, len(chapters), 2): if i1 len(chapters): chapter_list.append({ ‘title‘: chapters[i], ‘content‘: chapters[i1][:2000] # 只取前2000字符作为示例避免太长 }) return chapter_list chapters split_into_chapters(cleaned_text) print(f识别到 {len(chapters)} 个章节。) for i, chap in enumerate(chapters[:3]): # 打印前三个章节看看 print(f章节 {i1}: {chap[‘title‘]}) print(f内容预览: {chap[‘content‘][:100]}...\n)2.2 第二步提取核心信息这是解析器最核心也最有挑战的部分。我们将使用一些轻量级的自然语言处理库来帮忙。人物识别一个简单有效的方法是寻找文本中高频出现的、且符合中国人名特征的词汇。我们可以使用jieba库进行分词和词性标注然后筛选出人名。import jieba import jieba.posseg as pseg from collections import Counter def extract_characters(text, top_k10): 从文本中提取可能的人物名称。 策略找出高频的、被jieba标注为‘nr‘人名的词汇。 words pseg.cut(text) name_candidates [] for word, flag in words: if flag ‘nr‘ and len(word) 2: # 人名且长度至少为2 name_candidates.append(word) # 统计出现频率 name_counter Counter(name_candidates) # 返回出现频率最高的前top_k个作为主要人物候选 most_common_names name_counter.most_common(top_k) # 简单过滤掉一些常见的非人名高频词如地名、通用名词 common_non_names {‘中国‘, ‘美国‘, ‘公司‘, ‘先生‘, ‘小姐‘} characters [name for name, count in most_common_names if name not in common_non_names] return characters[:5] # 返回最有可能的前5个 # 对整部小说或第一章进行人物提取 sample_text chapters[0][‘content‘] if chapters else cleaned_text[:5000] potential_characters extract_characters(sample_text) print(f识别到的主要人物候选: {potential_characters})场景/地点识别方法与人物识别类似我们关注标注为‘ns‘地名的词汇。def extract_locations(text, top_k10): 从文本中提取可能的地点名称。 策略找出高频的、被jieba标注为‘ns‘地名的词汇。 words pseg.cut(text) location_candidates [] for word, flag in words: if flag ‘ns‘ and len(word) 2: location_candidates.append(word) location_counter Counter(location_candidates) most_common_locations location_counter.most_common(top_k) common_non_locations {‘今天‘, ‘明天‘, ‘时候‘} # 误判过滤 locations [loc for loc, count in most_common_locations if loc not in common_non_locations] return locations[:5] potential_locations extract_locations(sample_text) print(f识别到的主要地点候选: {potential_locations})关键情节摘要为每个章节生成一个简短的摘要帮助我们抓住故事脉络。这里我们可以用一个非常简单的“抽取式摘要”方法找出章节中最重要的句子通常通过词频或TF-IDF判断。from sklearn.feature_extraction.text import TfidfVectorizer import numpy as np def generate_summary(text, num_sentences2): 生成抽取式摘要非常基础的版本。 将文本分成句子用TF-IDF找出最具代表性的句子。 # 简单分句按句号、问号、感叹号分割 sentences re.split(r‘[。]‘, text) sentences [s.strip() for s in sentences if len(s.strip()) 5] # 过滤掉过短的句子 if len(sentences) num_sentences: return ‘。‘.join(sentences) ‘。‘ # 计算TF-IDF vectorizer TfidfVectorizer(tokenizerjieba.cut, stop_words[‘的‘, ‘了‘, ‘在‘, ‘是‘, ‘我‘]) try: tfidf_matrix vectorizer.fit_transform(sentences) except ValueError: # 可能所有句子都被过滤掉了 return text[:100] ‘...‘ # 计算每个句子的重要性得分TF-IDF向量之和 sentence_scores np.array(tfidf_matrix.sum(axis1)).flatten() # 选取得分最高的句子 top_sentence_indices sentence_scores.argsort()[-num_sentences:][::-1] top_sentence_indices.sort() # 按原文顺序排列 summary ‘。‘.join([sentences[i] for i in top_sentence_indices]) ‘。‘ return summary # 为第一章生成摘要 if chapters: first_chapter_summary generate_summary(chapters[0][‘content‘]) print(f第一章情节摘要: {first_chapter_summary})2.3 第三步结构化整理与输出信息提取出来后我们需要把它们整理成一种清晰、易读的格式方便后续手动筛选或直接提供给AI。JSON格式是个不错的选择。import json def create_story_material(chapters, overall_characters, overall_locations): 将解析出的信息结构化为一个字典。 story_material { metadata: { total_chapters: len(chapters), extracted_time: 2023-10-27 # 可以替换为动态时间 }, main_characters: overall_characters, main_locations: overall_locations, chapter_details: [] } # 为每个章节添加详细信息这里只处理前几个章节作为示例 for i, chap in enumerate(chapters[:3]): # 限制前3章避免太长 chapter_characters extract_characters(chap[‘content‘], top_k3) chapter_locations extract_locations(chap[‘content‘], top_k3) chapter_summary generate_summary(chap[‘content‘]) story_material[chapter_details].append({ chapter_index: i 1, chapter_title: chap[‘title‘], characters_involved: chapter_characters, locations_involved: chapter_locations, plot_summary: chapter_summary }) return story_material # 整合信息这里用整部小说文本进行整体人物地点提取用分章内容做详情 overall_chars extract_characters(cleaned_text[:20000], top_k8) # 用前2万字分析整体人物 overall_locs extract_locations(cleaned_text[:20000], top_k8) # 用前2万字分析整体地点 material create_story_material(chapters, overall_chars, overall_locs) # 将结构化数据保存为JSON文件 with open(‘story_material.json‘, ‘w‘, encoding‘utf-8‘) as f: json.dump(material, f, ensure_asciiFalse, indent2) print(小说素材已成功提取并保存至 ‘story_material.json‘ 文件。) print(*50) print(解析结果预览:) print(f主要人物: {material[‘main_characters‘]}) print(f主要地点: {material[‘main_locations‘]}) if material[‘chapter_details‘]: first_chap material[‘chapter_details‘][0] print(f\n第一章《{first_chap[‘chapter_title‘]}》概览:) print(f 涉及人物: {first_chap[‘characters_involved‘]}) print(f 涉及地点: {first_chap[‘locations_involved‘]}) print(f 情节摘要: {first_chap[‘plot_summary‘]})运行完上面的代码你就会得到一个story_material.json文件里面整齐地存放着从小说中提取出来的“食材”。3. 连接AI模型从素材到创作素材准备好了下一步就是“烹饪”——用水墨江南这样的AI模型进行再创作。这里的关键在于“提示词工程”。我们不能直接把JSON文件扔给AI而是要把结构化的信息转化成模型能理解的、富有画面感和故事性的语言描述。假设我们使用一个支持中文、擅长极简中式风格的文生图或故事生成模型例如通过其API或Web界面。我们的任务就是构建优质的提示词。基础提示词模板请基于以下故事要素创作一幅极简中式风格的图像/一个简短故事片段 **核心人物**[这里填入人物名例如李逍遥] **人物特征**[从原文推断或总结例如少年侠客机灵聪慧背负长剑] **核心场景**[这里填入地点名例如仙灵岛湖畔] **场景氛围**[描述氛围例如雾气缭绕荷花盛开静谧神秘] **情节启发**[基于章节摘要例如初次登岛寻找灵药心中既有期待又怀警惕] **风格要求**水墨画风格留白艺术色彩淡雅强调意境而非写实。具体操作示例读取素材从我们生成的JSON文件中加载数据。组合提示词编写一个函数随机或指定地选取人物、地点和情节填充到上述模板中。调用AI模型将生成的提示词发送给AI模型的API。这里以伪代码示意因为不同模型的调用方式各异。import random def generate_prompt_for_ai(story_material, chapter_index0): 根据解析出的小说素材生成用于AI创作的提示词。 details story_material[‘chapter_details‘][chapter_index] # 从该章节涉及的元素中选取如果列表为空则从全局选取 character random.choice(details[‘characters_involved‘] or story_material[‘main_characters‘]) location random.choice(details[‘locations_involved‘] or story_material[‘main_locations‘]) # 这里可以更智能地匹配人物特征和场景氛围例如建立一个小型知识库或使用更高级的NLP模型。 # 为简化我们使用固定描述或根据名称简单推断。 character_traits { ‘李逍遥‘: ‘少年侠客机灵聪慧眼神不羁‘, ‘赵灵儿‘: ‘少女清丽脱俗身世神秘善良温柔‘, # ... 可以预先定义或通过其他方式推断 } location_atmosphere { ‘仙灵岛‘: ‘雾气缭绕灵气充沛宛如世外桃源‘, ‘余杭镇‘: ‘江南水乡热闹市井客栈酒旗飘扬‘, # ... } trait character_traits.get(character, ‘一位故事人物‘) atmosphere location_atmosphere.get(location, ‘一个故事中的地点‘) prompt_template f“““ 请基于以下故事要素创作一幅极简中式风格的图像 **核心人物**{character} **人物特征**{trait} **核心场景**{location} **场景氛围**{atmosphere} **情节启发**{details[‘plot_summary‘]} **风格要求**水墨画风格留白艺术色彩淡雅以墨色、赭石、花青为主强调意境与氛围人物勾勒写意。 “““ return prompt_template # 生成提示词 ai_prompt generate_prompt_for_ai(material, chapter_index0) print(生成的AI提示词) print(ai_prompt) print(\n *50) print(你可以将此提示词复制到水墨江南等AI绘画或故事生成模型中引导其创作。)通过这种方式你就能将千变万化的小说内容转化为成百上千个不同的、高质量的AI创作指令。你可以为同一个人物在不同场景下生成画像也可以基于某个关键情节生成一系列故事漫画。4. 实践建议与扩展方向上面介绍的解析器是一个基础版本它能跑通流程提取出一些有用的信息。但如果你想让它更强大、更精准可以考虑下面几个扩展方向提升识别准确率目前基于词性标注的方法误判率不低。可以尝试构建自定义词典将小说中特有的人物名、地名提前加入jieba词典。使用预训练模型利用像LTP、HanLP或spaCy配合中文模型这类更强大的NLP工具包它们有更准确的分词、命名实体识别功能。规则后处理比如连续出现的两个单字人名很可能是一个完整人名如“李 逍遥”应合并。挖掘人物关系这是让“故事新编”更有深度的关键。可以分析人物共现的句子或者使用关系抽取模型来构建简单的人物关系图如李逍遥-爱慕-赵灵儿李逍遥-师徒-酒剑仙。情感分析与情节曲线对每个章节进行情感分析积极/消极可以绘制出故事的情感起伏曲线。你可以选择情感最强烈的章节如高潮、转折点作为AI创作的重点题材。构建可视化素材库将提取出的所有人物、地点、情节摘要做成一个简单的网页应用用图表和关系网可视化展示点击某个元素就能一键生成对应的AI创作提示词。全自动化管道将整个流程脚本化从监控小说更新、自动抓取新章节、解析、到定时提交任务给AI模型生成作品实现“小说追更-AI同人创作”的自动化流水线。5. 总结把Python脚本和AI模型结合起来自己动手打造一个从小说到创意作品的转换器这个过程本身就充满了乐趣。我们做的这个解析器虽然简单但它成功地在浩如烟海的文字和AI的生成能力之间架起了一座结构化的桥梁。它不再需要你手动去总结人物和情节而是自动地、批量地完成这些基础工作让你能把更多精力放在创意引导上——比如如何设计更巧妙的提示词如何将不同小说的元素进行“跨界”融合。当你看到水墨江南模型根据你提供的“李逍遥在锁妖塔”的素材生成出一幅你从未想象过的、充满悲壮与孤独感的极简水墨画时那种成就感是非常独特的。这个项目就像一个起点你可以用它来解构任何你喜欢的文本然后用不同的AI模型去尝试再创作。技术在这里不是目的而是帮你释放创意、探索故事无限可能性的工具。希望这个分享能给你带来一些灵感不妨找一本你喜欢的小说从运行第一行预处理代码开始试试看吧。获取更多AI镜像想探索更多AI镜像和应用场景访问 CSDN星图镜像广场提供丰富的预置镜像覆盖大模型推理、图像生成、视频生成、模型微调等多个领域支持一键部署。