随机文章生成器:Node.js与JSON数据的创意碰撞

前言

本篇文章将带您深入探索Node.jsJSON数据 的神奇结合,能够从静态的JSON文件中挖掘出鲜活的故事,还能通过智能化的算法随机生成文章。想象一下,只需轻轻一点,一篇充满创意和知识的文章便跃然纸上,这一切的背后,正是Node.js与JSON数据的巧妙运用,快和我一起往下看看吧~

正文

文件布局

终端输入: npm init -y

在生成的package.json文件添加一个 "type": "module",从而可以通过import引入模块

data.json

yaml 复制代码
{
  "title": [
    "一天掉多少根头发",
    "中午吃什么",
    "学生会退会",
    "好好学习",
    "生活的意义",
    "科学和人文谁更有意义",
    "熬夜一时爽"
  ],
  "famous":[
    "爱迪生{{said}},天才是百分之一的勤奋加百分之九十九的汗水。{{conclude}}",
    "查尔斯·史{{said}},一个人几乎可以在任何他怀有无限热忱的事情上成功。{{conclude}}",
    "培根说过,深窥自己的心,而后发觉一切的奇迹在你自己。{{conclude}}",
    "歌德曾经{{said}},流水在碰到底处时才会释放活力。{{conclude}}",
    "莎士比亚{{said}},那脑袋里的智慧,就像打火石里的火花一样,不去打它是不肯出来的。{{conclude}}",
    "戴尔·卡耐基{{said}},多数人都拥有自己不了解的能力和机会,都有可能做到未曾梦想的事情。{{conclude}}",
    "白哲特{{said}},坚强的信念能赢得强者的心,并使他们变得更坚强。{{conclude}}",
    "伏尔泰{{said}},不经巨大的困难,不会有伟大的事业。{{conclude}}",
    "富勒曾经{{said}},苦难磨炼一些人,也毁灭另一些人。{{conclude}}",
    "文森特·皮尔{{said}},改变你的想法,你就改变了自己的世界。{{conclude}}",
    "拿破仑·希尔{{said}},不要等待,时机永远不会恰到好处。{{conclude}}",
    "塞涅卡{{said}},生命如同寓言,其价值不在与长短,而在与内容。{{conclude}}",
    "奥普拉·温弗瑞{{said}},你相信什么,你就成为什么样的人。{{conclude}}",
    "吕凯特{{said}},生命不可能有两次,但许多人连一次也不善于度过。{{conclude}}",
    "莎士比亚{{said}},人的一生是短的,但如果卑劣地过这一生,就太长了。{{conclude}}",
    "笛卡儿{{said}},我的努力求学没有得到别的好处,只不过是愈来愈发觉自己的无知。{{conclude}}",
    "左拉{{said}},生活的道路一旦选定,就要勇敢地走到底,决不回头。{{conclude}}",
    "米歇潘{{said}},生命是一条艰险的峡谷,只有勇敢的人才能通过。{{conclude}}",
    "吉姆·罗恩{{said}},要么你主宰生活,要么你被生活主宰。{{conclude}}",
    "日本谚语{{said}},不幸可能成为通向幸福的桥梁。{{conclude}}",
    "海贝尔{{said}},人生就是学校。在那里,与其说好的教师是幸福,不如说好的教师是不幸。{{conclude}}",
    "杰纳勒尔·乔治·S·巴顿{{said}},接受挑战,就可以享受胜利的喜悦。{{conclude}}",
    "德谟克利特{{said}},节制使快乐增加并使享受加强。{{conclude}}",
    "裴斯泰洛齐{{said}},今天应做的事没有做,明天再早也是耽误了。{{conclude}}",
    "歌德{{said}},决定一个人的一生,以及整个命运的,只是一瞬之间。{{conclude}}",
    "卡耐基{{said}},一个不注意小事情的人,永远不会成就大事业。{{conclude}}",
    "卢梭{{said}},浪费时间是一桩大罪过。{{conclude}}",
    "康德{{said}},既然我已经踏上这条道路,那么,任何东西都不应妨碍我沿着这条路走下去。{{conclude}}",
    "克劳斯·莫瑟爵士{{said}},教育需要花费钱,而无知也是一样。{{conclude}}",
    "伏尔泰{{said}},坚持意志伟大的事业需要始终不渝的精神。{{conclude}}",
    "亚伯拉罕·林肯{{said}},你活了多少岁不算什么,重要的是你是如何度过这些岁月的。{{conclude}}",
    "韩非{{said}},内外相应,言行相称。{{conclude}}",
    "富兰克林{{said}},你热爱生命吗?那么别浪费时间,因为时间是组成生命的材料。{{conclude}}",
    "马尔顿{{said}},坚强的信心,能使平凡的人做出惊人的事业。{{conclude}}",
    "笛卡儿{{said}},读一切好书,就是和许多高尚的人谈话。{{conclude}}",
    "塞涅卡{{said}},真正的人生,只有在经过艰难卓绝的斗争之后才能实现。{{conclude}}",
    "易卜生{{said}},伟大的事业,需要决心,能力,组织和责任感。{{conclude}}",
    "歌德{{said}},没有人事先了解自己到底有多大的力量,直到他试过以后才知道。{{conclude}}",
    "达尔文{{said}},敢于浪费哪怕一个钟头时间的人,说明他还不懂得珍惜生命的全部价值。{{conclude}}",
    "佚名{{said}},感激每一个新的挑战,因为它会锻造你的意志和品格。{{conclude}}",
    "奥斯特洛夫斯基{{said}},共同的事业,共同的斗争,可以使人们产生忍受一切的力量。 {{conclude}}",
    "苏轼{{said}},古之立大事者,不惟有超世之才,亦必有坚忍不拔之志。{{conclude}}",
    "王阳明{{said}},故立志者,为学之心也;为学者,立志之事也。{{conclude}}",
    "歌德{{said}},读一本好书,就如同和一个高尚的人在交谈。{{conclude}}",
    "乌申斯基{{said}},学习是劳动,是充满思想的劳动。{{conclude}}",
    "别林斯基{{said}},好的书籍是最贵重的珍宝。{{conclude}}",
    "富兰克林{{said}},读书是易事,思索是难事,但两者缺一,便全无用处。{{conclude}}",
    "鲁巴金{{said}},读书是在别人思想的帮助下,建立起自己的思想。{{conclude}}",
    "培根{{said}},合理安排时间,就等于节约时间。{{conclude}}",
    "屠格涅夫{{said}},你想成为幸福的人吗?但愿你首先学会吃得起苦。{{conclude}}",
    "莎士比亚{{said}},抛弃时间的人,时间也抛弃他。{{conclude}}",
    "叔本华{{said}},普通人只想到如何度过时间,有才能的人设法利用时间。{{conclude}}",
    "博{{said}},一次失败,只是证明我们成功的决心还够坚强。 维{{conclude}}",
    "拉罗什夫科{{said}},取得成就时坚持不懈,要比遭到失败时顽强不屈更重要。{{conclude}}",
    "莎士比亚{{said}},人的一生是短的,但如果卑劣地过这一生,就太长了。{{conclude}}",
    "俾斯麦{{said}},失败是坚忍的最后考验。{{conclude}}",
    "池田大作{{said}},不要回避苦恼和困难,挺起身来向它挑战,进而克服它。{{conclude}}",
    "莎士比亚{{said}},那脑袋里的智慧,就像打火石里的火花一样,不去打它是不肯出来的。{{conclude}}",
    "希腊{{said}},最困难的事情就是认识自己。{{conclude}}",
    "黑塞{{said}},有勇气承担命运这才是英雄好汉。{{conclude}}",
    "非洲{{said}},最灵繁的人也看不见自己的背脊。{{conclude}}",
    "培根{{said}},阅读使人充实,会谈使人敏捷,写作使人精确。{{conclude}}",
    "斯宾诺莎{{said}},最大的骄傲于最大的自卑都表示心灵的最软弱无力。{{conclude}}",
    "西班牙{{said}},自知之明是最难得的知识。{{conclude}}",
    "塞内加{{said}},勇气通往天堂,怯懦通往地狱。{{conclude}}",
    "赫尔普斯{{said}},有时候读书是一种巧妙地避开思考的方法。{{conclude}}",
    "笛卡儿{{said}},阅读一切好书如同和过去最杰出的人谈话。{{conclude}}",
    "邓拓{{said}},越是没有本领的就越加自命不凡。{{conclude}}",
    "爱尔兰{{said}},越是无能的人,越喜欢挑剔别人的错儿。{{conclude}}",
    "老子{{said}},知人者智,自知者明。胜人者有力,自胜者强。{{conclude}}",
    "歌德{{said}},意志坚强的人能把世界放在手中像泥块一样任意揉捏。{{conclude}}",
    "迈克尔·F·斯特利{{said}},最具挑战性的挑战莫过于提升自我。{{conclude}}",
    "爱迪生{{said}},失败也是我需要的,它和成功对我一样有价值。{{conclude}}",
    "罗素·贝克{{said}},一个人即使已登上顶峰,也仍要自强不息。{{conclude}}",
    "马云{{said}},最大的挑战和突破在于用人,而用人最大的突破在于信任人。{{conclude}}",
    "雷锋{{said}},自己活着,就是为了使别人过得更美好。{{conclude}}",
    "布尔沃{{said}},要掌握书,莫被书掌握;要为生而读,莫为读而生。{{conclude}}",
    "培根{{said}},要知道对好事的称颂过于夸大,也会招来人们的反感轻蔑和嫉妒。{{conclude}}",
    "莫扎特{{said}},谁和我一样用功,谁就会和我一样成功。{{conclude}}",
    "马克思{{said}},一切节省,归根到底都归结为时间的节省。{{conclude}}",
    "莎士比亚{{said}},意志命运往往背道而驰,决心到最后会全部推倒。{{conclude}}",
    "卡莱尔{{said}},过去一切时代的精华尽在书中。{{conclude}}",
    "培根{{said}},深窥自己的心,而后发觉一切的奇迹在你自己。{{conclude}}",
    "罗曼·罗兰{{said}},只有把抱怨环境的心情,化为上进的力量,才是成功的保证。{{conclude}}",
    "孔子{{said}},知之者不如好之者,好之者不如乐之者。{{conclude}}",
    "达·芬奇{{said}},大胆和坚定的决心能够抵得上武器的精良。{{conclude}}",
    "叔本华{{said}},意志是一个强壮的盲人,倚靠在明眼的跛子肩上。{{conclude}}",
    "黑格尔{{said}},只有永远躺在泥坑里的人,才不会再掉进坑里。{{conclude}}",
    "普列姆昌德{{said}},希望的灯一旦熄灭,生活刹那间变成了一片黑暗。{{conclude}}",
    "维龙{{said}},要成功不需要什么特别的才能,只要把你能做的小事做得好就行了。{{conclude}}",
    "郭沫若{{said}},形成天才的决定因素应该是勤奋。{{conclude}}",
    "洛克{{said}},学到很多东西的诀窍,就是一下子不要学很多。{{conclude}}",
    "西班牙{{said}},自己的鞋子,自己知道紧在哪里。{{conclude}}",
    "拉罗什福科{{said}},我们唯一不会改正的缺点是软弱。{{conclude}}",
    "亚伯拉罕·林肯{{said}},我这个人走得很慢,但是我从不后退。{{conclude}}",
    "美华纳{{said}},勿问成功的秘诀为何,且尽全力做你应该做的事吧。{{conclude}}",
    "俾斯麦{{said}},对于不屈不挠的人来说,没有失败这回事。{{conclude}}",
    "阿卜·日·法拉兹{{said}},学问是异常珍贵的东西,从任何源泉吸收都不可耻。{{conclude}}",
    "白哲特{{said}},坚强的信念能赢得强者的心,并使他们变得更坚强。 {{conclude}}",
    "查尔斯·史考伯{{said}},一个人几乎可以在任何他怀有无限热忱的事情上成功。 {{conclude}}",
    "贝多芬{{said}},卓越的人一大优点是:在不利与艰难的遭遇里百折不饶。{{conclude}}",
    "莎士比亚{{said}},本来无望的事,大胆尝试,往往能成功。{{conclude}}",
    "卡耐基{{said}},我们若已接受最坏的,就再没有什么损失。{{conclude}}",
    "德国{{said}},只有在人群中间,才能认识自己。{{conclude}}",
    "史美尔斯{{said}},书籍把我们引入最美好的社会,使我们认识各个时代的伟大智者。{{conclude}}",
    "冯学峰{{said}},当一个人用工作去迎接光明,光明很快就会来照耀着他。{{conclude}}",
    "吉格·金克拉{{said}},如果你能做梦,你就能实现它。{{conclude}}"
  ],
  "bosh_before": [
    "既然如此,",
    "那么,",
    "我认为,",
    "一般来说,",
    "总结的来说,",
    "无论如何,",
    "经过上述讨论,",
    "这样看来,",
    "从这个角度来看,",
    "现在,解决{{title}}的问题,是非常非常重要的。 所以,",
    "每个人都不得不面对这些问题。在面对这种问题时,",
    "我们不得不面对一个非常尴尬的事实,那就是,",
    "而这些并不是完全重要,更加重要的问题是,",
    "我们不妨可以这样来想: "
  ],
  "bosh":[
    "{{title}}的发生,到底需要如何做到,不{{title}}的发生,又会如何产生。 ",
    "{{title}},到底应该如何实现。 ",
    "带着这些问题,我们来审视一下{{title}}。 ",
    "所谓{{title}},关键是{{title}}需要如何写。 ",
    "我们一般认为,抓住了问题的关键,其他一切则会迎刃而解。",
    "问题的关键究竟为何? ",
    "{{title}}因何而发生?",
    "一般来讲,我们都必须务必慎重的考虑考虑。 ",
    "要想清楚,{{title}},到底是一种怎么样的存在。 ",
    "了解清楚{{title}}到底是一种怎么样的存在,是解决一切问题的关键。",
    "就我个人来说,{{title}}对我的意义,不能不说非常重大。 ",
    "本人也是经过了深思熟虑,在每个日日夜夜思考这个问题。 ",
    "{{title}},发生了会如何,不发生又会如何。 ",
    "在这种困难的抉择下,本人思来想去,寝食难安。",
    "生活中,若{{title}}出现了,我们就不得不考虑它出现了的事实。 ",
    "这种事实对本人来说意义重大,相信对这个世界也是有一定意义的。",
    "我们都知道,只要有意义,那么就必须慎重考虑。",
    "这是不可避免的。 ",
    "可是,即使是这样,{{title}}的出现仍然代表了一定的意义。 ",
    "{{title}}似乎是一种巧合,但如果我们从一个更大的角度看待问题,这似乎是一种不可避免的事实。 ",
    "在这种不可避免的冲突下,我们必须解决这个问题。 ",
    "对我个人而言,{{title}}不仅仅是一个重大的事件,还可能会改变我的人生。 "
  ],
  "conclude":[
    "这不禁令我深思。 ",
    "带着这句话,我们还要更加慎重的审视这个问题: ",
    "这启发了我。",
    "我希望诸位也能好好地体会这句话。 ",
    "这句话语虽然很短,但令我浮想联翩。",
    "这句话看似简单,但其中的阴郁不禁让人深思。",
    "这句话把我们带到了一个新的维度去思考这个问题:",
    "这似乎解答了我的疑惑。"
  ],
  "said":[
    "曾经说过",
    "在不经意间这样说过",
    "说过一句著名的话",
    "曾经提到过",
    "说过一句富有哲理的话"
  ]
}

lib/random.js

randomInt 函数

用于生成一个介于 minmax(包含两端点)之间的随机整数:

  • Math.random() 生成一个介于 0(含)和 1(不含)之间的随机浮点数;
  • 通过 min * (1 - n) + max * n将这个浮点数映射到 minmax 之间;
  • Math.floor() 函数用于向下取整,确保返回的是整数。

createRandomPicker 函数

用于创建一个可以随机从数组中选取元素的函数 randomPick

  • 通过arr = [...arr]; 创建了 arr 的浅拷贝,保证原始数组不会被修改;
  • randomPick 函数,返回arr中的随机元素;
  • 在返回 randomPick 函数之前先调用一次,打乱数组中的元素;
  • 返回 randomPick 函数,使其可以在外部被调用。
ini 复制代码
export function randomInt(min, max) {
   const n = Math.random();
   return Math.floor(min * (1 - n) + max * n);
};

export function createRandomPicker(arr) {
    arr = [...arr]; // 创建原数组的浅拷贝,避免修改原数组

    function randomPick() {
        const len = arr.length - 1;
        const index = randomInt(0, arr.length);
        [arr[index], arr[len]] = [arr[len], arr[index]];    
        return arr[index];
    };

    randomPick(); // 放弃第一次的结果
    return randomPick;

}

lib/generator.js

  • 导入 randomIntcreateRandomPicker 函数;

sentence 函数

该函数接收一个函数 pick 和一个替换器对象 replacer

  1. pick 函数用于从预定义的数组中随机选择一个句子;
  2. 遍历 replacer 对象,使用相应的值替换掉字符串中的占位符.

generate 函数

用于生成文章,接受标题 title 和一个配置对象作为参数。(配置对象包括 corpus (要传入的json数据),以及可选的 minmax 来定义文章的长度范围)

  1. 通过 randomInt 确定文章的总长度 articleLength
  2. corpus 中提取不同类型的句子集合,并对每一类使用 createRandomPicker 创建随机选择函数;
  3. 使用循环来生成文章直到达到指定的长度:
  • 选择一个段落长度 sectionLength
  • 再次循环直到段落长度达到要求,每次迭代根据随机概率选择不同类型的句子并调用 sentence 函数填充内容;
  • 将生成的段落追加到文章中,并更新文章的总长度。
    1. 当文章达到所需长度时,返回生成的文章列表。
ini 复制代码
import { randomInt, createRandomPicker } from './random.js';

// 替换文本
function sentence(pick, replacer) {
    let ret = pick(); // 得到一个句子
    for (const key in replacer) {
        ret = ret.replace(new RegExp(`{{${key}}}`, 'g'), // 'g'全局替换
        typeof replacer[key] === 'function' ? replacer[key]() : replacer[key]
        );
    }

    return ret;
}

export function generate(title, { corpus, min = 500, max = 800 }) {
    const articleLength = randomInt(min, max);
    const { famous, bosh_before, bosh, conclude, said} = corpus;
    const [pickFamous, pickBoshBefore, pickBosh, pickConclude, pickSaid] 
    = [famous, bosh_before, bosh, conclude, said].map(createRandomPicker);

    const article = [];
    let totalLength = 0;

    while (totalLength < articleLength) {// 生成文章
        let section = '';
        const sectionLength = randomInt(100, 300);// 段落长度

        while(section.length < sectionLength) { // 生成段落
            const n = randomInt(0, 100);// 百分比
            if(n < 20) {
                section += sentence(pickFamous, { said: pickSaid, conclude: pickConclude });
            }
            else if(n < 50) {
                section += sentence(pickBoshBefore, { title }) + sentence(pickBosh, { title });
            }
            else {
                section += sentence(pickBosh, { title });
            }
        }

        totalLength += section.length;
        article.push(section);
    }

    return article;
}

index.js

从本地加载数据,生成一篇文章,并将文章保存到本地文件中。

  • 通过import引入库;

加载数据

  • 通过import.meta.url 获取当前脚本的绝对路径url,即当前执行的JavaScript文件的url;
  • 通过 fileURLToPath 将url转换为文件系统路径;
  • 通过 resolvedirname 结合 import.meta.url 来获取当前文件的目录路径,然后拼接上相对路径 "./corpus/data.json" 来得到要读取的数据文件的完整路径;
  • 通过 fs.readFileSync同步 的方式读取数据文件的内容,并指定编码为 "utf-8"
  • 通过 JSON.parse 将读取的字符串转换为JavaScript对象。

生成文章

  • 通过 loadCorpus 函数加载数据到 corpus 变量;
  • 通过 createRandomPicker 创建一个随机选择函数 pickTitle,这个函数用于从 corpus.title 数组中随机选取一个标题;
  • 通过 pickTitle 来获得一个随机标题;
  • 通过 generate 函数,传入随机标题和语料库 corpus,生成一篇文章,存储在 article 变量中。

保存文章

  • 通过 fs.writeFileSync 同步地将文章写入到文件中。文件名由 title 和扩展名 .txt 构成,存储在 ./output/ 目录下;
  • 通过 article.join('\n ') 将文章数组转换为字符串,其中每个段落之间使用换行符加上三个空格 \n 分隔。
javascript 复制代码
import fs from "fs";
import { fileURLToPath } from "url";
import { dirname, resolve } from "path";
import { generate } from "./lib/generator.js";
import { createRandomPicker } from "./lib/random.js";

function loadCorpus(src) {
    const url = import.meta.url;// 读取当前脚本的绝对路径 拿到index.js的绝对路径
    const path = resolve(dirname(fileURLToPath(url)), "./curpus/data.json"); // 将拿到的路径格式化成绝对路径
    const data = fs.readFileSync(path, { encoding: "utf-8" });// 通过拿到的绝对路径来读取文件

    return JSON.parse(data);
}

const corpus = loadCorpus("./curpus/data.json");
const pickTitle = createRandomPicker(corpus.title);
const title = pickTitle();
const article = generate(title, { corpus });

fs.writeFileSync(`./output/${title}.txt`, article.join('\n   '));

结语

相关推荐
杰哥在此4 小时前
Java面试题:讨论持续集成/持续部署的重要性,并描述如何在项目中实施CI/CD流程
java·开发语言·python·面试·编程
强迫老板HelloWord4 小时前
前端JS特效第22波:jQuery滑动手风琴内容切换特效
前端·javascript·jquery
luanluan88885 小时前
维护el-table列,循环生成el-table
javascript·vue.js·ecmascript·element plus
续亮~6 小时前
9、程序化创意
前端·javascript·人工智能
青青草原上的梦想家6 小时前
Cocos Creator 游戏性能优化指南
游戏·面试·性能优化·typescript
刘铸纬6 小时前
Golang中defer和return顺序
开发语言·后端·golang
38kcok9w2vHanx_6 小时前
从0开始搭建vue项目
前端·javascript·vue.js
EthanWsir7 小时前
嵌入式C语言面试相关知识——关键字(不定期更新)
c语言·开发语言·面试
2301_807353407 小时前
v-if条件渲染及v-show的选择
前端·javascript·vue.js
多多*7 小时前
每天一道面试题之浅浅讲一下java5中的自动装箱和自动拆箱
java·开发语言·spring boot·后端·spring