Node.js实现一个文章生成器

前言

本文将从零开始,讲解如何使用Node.js来实现一个文章生成器

node里面有很多优秀的模块,现在我们就借助node的fs模块来操控文本,来实现我们想要的效果

效果展示

动画.gif

  • 体验 fs

首先我们先创建一个json文件

image.png

里面放一些内容

image.png

接下来我们书写代码

import fs from "fs";
const data = fs.readFileSync("./cuepus/data.json", "utf-8", (err, data) => {if (!err) {// console.log(data);} else {console.log(err);}
});

image.png

可以看到我们就能读取到文件里的数据,这里我们体验了fs里面强大的功能

在这里我们放了文章的一些必须点,如文章内容、标题等,通过随机拿取数据生成一个文章

image.png

这里我们通过

import { fileURLToPath } from "url";
import { dirname,resolve } from "path";

去操控获取绝对路径

const url = import.meta.url;// 获取当前文件的绝对路径 
console.log(url);
console.log(fileURLToPath(url));
console.log(dirname(fileURLToPath(url)));
// 获取文件的绝对路径
const path = resolve(dirname(fileURLToPath(url)), "./cuepus/data.json"); console.log(path);
  1. const url = import.meta.url; :使用了import.meta 对象来获取当前模块文件的绝对 URL 路径,并将其赋值给变量 url
  2. console.log(fileURLToPath(url)); :将url路径转换为文件系统路径
  3. console.log(dirname(fileURLToPath(url))); :将url转换为文件系统路径,然后通过 dirname 函数获取该路径的目录部分
  4. const path = resolve(dirname(fileURLToPath(url)), "./cuepus/data.json"); :将前面获取到的目录部分和相对路径 "./cuepus/data.json" 进行组合,生成一个完整的文件绝对路径,并将其赋值给变量 path

接下来我们代码就可以写成以下的形式

import fs from "fs";
import { fileURLToPath } from "url";
import { dirname,resolve } from "path";const url = import.meta.url;// 获取当前文件的绝对路径
// 获取文件的绝对路径
const path = resolve(dirname(fileURLToPath(url)), "./cuepus/data.json");
const data = fs.readFileSync(path, "utf-8", (err, data) => {if (!err) {// console.log(data);} else {console.log(err);}
});console.log(JSON.parse(data));

接下来我们写封装两个函数

random.js

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 - 1const index = randomInt(0, len);[arr[index], arr[len]] = [arr[len], arr[index]]return arr[index]}randomPick()  // 放弃第一次结果return randomPick
}

首先,定义了一个名为 randomInt 的导出函数,它接受两个参数 minmax ,用于生成指定范围内的随机整数。

然后,定义了一个名为 createRandomPicker 的导出函数,它接受一个数组 arr 作为参数。

在函数内部,先对传入的数组进行了复制,以避免修改原始数组。

接着,定义了一个内部函数 randomPick ,它的功能是:

  1. 计算数组的有效长度。
  2. 生成一个在有效范围内的随机索引。
  3. 通过交换将随机索引处的元素与最后一个元素交换位置。
  4. 返回交换后的随机索引处的元素。

在函数体中,首先调用了一次 randomPick 函数,但放弃了这次的结果。

最后,返回 randomPick 函数,以便外部可以调用它来获取随机抽取的数组元素。

generator.js

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'), typeof replacer[key] === 'function' ? replacer[key]() : replacer[key]) }return ret
}export function generate(title, { corpus, min = 500, max = 800 }) {const articleLenth = randomInt(min, max)const { famous, bosh_before, bosh, conclude, said } = corpusconst [pickFamous, pickBoshBefore, pickBosh, pickConclude, pickSaid] = [famous, bosh_before, bosh, conclude, said].map(createRandomPicker)const article = []let totalLength = 0while (totalLength < articleLenth) {  // 生成文章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.lengtharticle.push(section)}return article
}

'./random.js' 模块导入了 randomIntcreateRandomPicker 两个函数。

然后,定义了 sentence 函数,它接受两个参数 pickreplacer

pick 函数用于获取一个句子,然后通过遍历 replacer 对象中的键,使用正则表达式匹配并替换句子中特定的模板字符串(形如 {{key}} )。如果对应的值是函数,则调用函数获取结果进行替换,否则直接使用值进行替换。

接下来,定义了 generate 函数,它接受三个参数:title 、一个包含配置信息的对象(包含 corpus 以及可选的 minmax )。

在函数内部:

  1. 通过 randomInt 生成一个在 minmax 范围内的文章长度 articleLenth
  2. corpus 对象中解构出几个部分,并对每个部分使用 createRandomPicker 函数创建随机选择器。
  3. 通过一个循环生成文章内容,每次循环生成一个段落。在生成段落的过程中,根据随机数决定使用不同的句子生成方式,并通过 sentence 函数进行处理和组合。
  4. 不断累加段落的长度,直到总长度达到 articleLenth ,最终将生成的文章段落组成一个数组返回。

最后调用即可,修改index.js

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  // 读取当前脚本的绝对路径const path = resolve(dirname(fileURLToPath(url)), src)const data = fs.readFileSync(path, {encoding: 'utf8'})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(''));

总结

本文本文将从零开始,讲解如何使用Node.js来实现一个文章生成器

希望看到这里的你能够有所收获!!!!自己动手实现一个简易的文章生成器吧

后期可以结合AI去实现更加智能的文章生成器

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/866644.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

抖音本地生活服务商入驻要求中暗含哪些信息?入局要点都在里面了!

随着抖音外卖的正式开放&#xff0c;许多创业者对于做抖音本地生活服务商的意向愈发强烈&#xff0c;抖音本地生活服务商入驻要求及相关话题更是在多个创业者群内被翻来覆去地讨论&#xff0c;且多次刷屏。 而就抖音目前在本地生活市场的布局来看&#xff0c;其主要的重心还是…

Renderless 思想正在影响前端开发

本文由前端小伙伴方长_beezen 原创。欢迎大家踊跃投稿。 原文链接&#xff1a;https://juejin.cn/post/7385752495535472655 前言 截止到 2024 年&#xff0c;跨端应用开发所需要考虑的兼容性&#xff0c;已经涵盖了框架、平台和设备类型等多个方面&#xff0c;例如&#xff1…

开发在线教育项目-在线课程视频网站开发

用了哪些技术 后端技术 springboot3 security权限框架&#xff08;后台&#xff09;mybatisPlus框架jwt生成tokeneasyexcel导入导出递归查询拦截器校验tokenredis的zset做排行榜功能redis的list做最新课程的功能redis做为缓存技术redis作为计数器&#xff0c;实时记录浏览量&…

搞定Loki+Promtail轻量级日志系统

Promtail 是 Loki 的日志收集客户端&#xff0c;它的主要功能是从各种来源收集日志并将其发送到 Loki 进行存储和查询。Promtail 的设计使其能够高效地收集和处理日志数据。 promtail-config.yaml&#xff08;配置&#xff09;: Promtail 读取配置文件&#xff08;例如 promta…

初阶数据结构二叉树练习系列(1)

这个系列的文章将带大家一起刷题&#xff0c;并且总结思路 温馨提示&#xff1a;本篇文章里的练习题仅适合刚学完二叉树的小白使用 相同的树 思路 情况分析&#xff1a;第一种情况&#xff1a;两棵树都为空 → 返回true 第二种情况&am…

C++ 引用——引用的基本语法

引用的基本使用 作用&#xff1a;给变量起别名 语法&#xff1a;数据类型 &别名 原名 示例&#xff1a; 运行结果&#xff1a;

如何利用Kimi解读Kimi的KVCache技术细节

最近Kimi公布了一篇Mooncake: Kimis KVCache-centric Architecture for LLM Serving的文章&#xff0c;详细介绍了Kimi背后的推理架构&#xff0c;因此笔者想到用Kimi解读Kimi&#xff0c;梳理相关技术要点如下&#xff0c;供大家参考&#xff1a; 文章 "Mooncake: A KVCa…

JVM原理(三):JVM对象回收判定机制与回收算法

如何判断一个对象是否存活(即是否还分配在堆中)&#xff0c;那看他是否还在用。 1. 引用计数算法 这是一种判断方式&#xff0c;相应的方法就是&#xff1a;如果一个对象被引用&#xff0c;那将被引用的对象中的一个计数器加一&#xff0c;引用失效就减一。在任何时刻引用计数…

STM32自己从零开始实操07:电机电路原理图

一、LC滤波电路 其实以下的滤波都可以叫低通滤波器。 1.1倒 “L” 型 LC 滤波电路 1.1.1定性分析 1.1.2仿真实验 电感&#xff1a;通低频阻高频的。仿真中高频信号通过电感&#xff0c;因为电感会阻止电流发生变化&#xff0c;故说阻止高频信号 电容&#xff1a;隔直通交。…

免费分享:中国三级及以上河流(附下载方法)

河流分级法的分级方法是从源头最小河流开始,称为一级河流;两条一级河流汇合成二级河流;以此类推,三级河流等等;最后是干流。本文将介绍中国三级及以上河流数据。 数据简介 1:100万中国三级及以上河流矢量数据是涵盖了全国范围内三级及以上级别河流的详细地理信息和空间分布。这…

App Store迎来了重磅更新,ASO冲榜优化或将成为不可或缺的一部分

近日App Store搜索页面迎来了重磅更新&#xff0c;苹果应用商店中搜索页面原有的热搜关键词消失了取而代之的是直接将排行榜放在了搜索顶部&#xff0c;分别是APP排行和游戏排行两部分。如下图&#xff1a; 很多人应该都是参考排行榜来下载APP的&#xff0c;这次更新之后用户在…

基于工业互联网的智能制造:未来制造业的新引擎

随着科技的飞速发展&#xff0c;工业互联网通过提供强大的数据支撑和通信基础&#xff0c;成为智能制造的重要基石。智能制造的引入&#xff0c;不仅显著提升了制造业的生产效率、降低了成本&#xff0c;而且提高了产品质量&#xff0c;满足了市场的多样化、个性化需求。 智能制…

解决问题:使用PageHelper.startPage和PageInfo实现分页,但是得到的total和传入的页面大小pageSize一样

我们需要的是total得到的数值是数据库里所有数据的条数。 1、包别引错 <!--PageHelper开始--><dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper-spring-boot-starter</artifactId><version>1.4.6</…

kafka 生产者

生产者 生产者负责创建消息&#xff0c;然后将其投递到Kafka中。 负载均衡 轮询策略。随机策略。按照 key 进行hash。 Kafka 的默认分区策略&#xff1a;如果指定了 key&#xff0c;key 相同的消息会发送到同一个分区&#xff08;分区有序&#xff09;&#xff1b;如果没有…

光伏储能电厂设备连接iec61850平台解决方案

在当今日益发展的电力系统中&#xff0c;光伏储能技术以其独特的优势逐渐崭露头角&#xff0c;成为可再生能源领域的重要组成部分。而在光伏储能系统的运行与监控中&#xff0c;通信协议的选择与实现则显得至关重要。本文将重点介绍光伏储能系统中的Modbus协议、电力IEC 61850平…

reids一主多从配置

-----------------跳过了安装redis的过程--------------------------- 主192.168.25.129从 192.168.25.130从 192.168.25.133 redis主从复制环境&#xff0c;基本上都是在从服务器上修改相关的配置 1、在俩台从服务器分别给 reids.conf文件添加master…

【深度学习练习】心脏病预测

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 一、什么是RNN RNN与传统神经网络最大的区别在于&#xff0c;每次都会将前一次的输出结果&#xff0c;带到下一隐藏层中一起训练。如下图所示&#xff1a; …

Docker 运行Nacos无法访问地址解决方法

参考我的上一篇文章去配置好镜像加速器&#xff0c;镜像加速器不是配置越多越好&#xff0c;重试次数多了会失败 Dockerhub无法拉取镜像配置阿里镜像加速器-CSDN博客 错误的尝试 最开始按照网上的方式去配了一大堆&#xff0c;发现下不下来。 镜像源地址&#xff1a;https:…

Oracle 解决4031错误

一、问题描述 什么是4031错误和4031错误产生的原因: 简单一个句话概括: 由于服务器一直在执行大量的硬解析,导致Oracle 的shared pool Free空间碎片过多,大的chunk不足, 当又一条复杂的sql语句要硬解析时, 缺少1个足够大的Free chunk, 通常就会报4031错误. 二、解决方法 临…