前言
本文將從零開始,講解如何使用Node.js來實現一個文章生成器
node裡面有很多優秀的模組,現在我們就藉助node的fs模組來操控文字,來實現我們想要的效果
效果展示
體驗 fs
首先我們先建立一個json檔案
裡面放一些內容
接下來我們書寫程式碼
import fs from "fs"; const data = fs.readFileSync("./cuepus/data.json", "utf-8", (err, data) => { if (!err) { // console.log(data); } else { console.log(err); } });
可以看到我們就能讀取到檔案裡的資料,這裏我們體驗了fs裡面強大的功能
在這裏我們放了文章的一些必須點,如文章內容、標題等,透過隨機拿取資料生成一個文章
這裏我們透過
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);
const url = import.meta.url;
:使用了import.meta
物件來獲取當前模組檔案的絕對 URL 路徑,並將其賦值給變數url
。console.log(fileURLToPath(url));
:將url路徑轉換為檔案系統路徑console.log(dirname(fileURLToPath(url)));
:將url轉換為檔案系統路徑,然後透過dirname
函式獲取該路徑的目錄部分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 - 1 const index = randomInt(0, len); [arr[index], arr[len]] = [arr[len], arr[index]] return arr[index] } randomPick() // 放棄第一次結果 return randomPick }
首先,定義了一個名為 randomInt
的匯出函式,它接受兩個引數 min
和 max
,用於生成指定範圍內的隨機整數。
然後,定義了一個名為 createRandomPicker
的匯出函式,它接受一個數組 arr
作為引數。
在函式內部,先對傳入的陣列進行了複製,以避免修改原始陣列。
接著,定義了一個內部函式 randomPick
,它的功能是:
計算陣列的有效長度。
生成一個在有效範圍內的隨機索引。
透過交換將隨機索引處的元素與最後一個元素交換位置。
返回交換後的隨機索引處的元素。
在函式體中,首先呼叫了一次 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 } = corpus const [pickFamous, pickBoshBefore, pickBosh, pickConclude, pickSaid] = [famous, bosh_before, bosh, conclude, said].map(createRandomPicker) const article = [] let totalLength = 0 while (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.length article.push(section) } return article }
從 './random.js'
模組匯入了 randomInt
和 createRandomPicker
兩個函式。
然後,定義了 sentence
函式,它接受兩個引數 pick
和 replacer
。
pick
函式用於獲取一個句子,然後透過遍歷 replacer
物件中的鍵,使用正規表示式匹配並替換句子中特定的模板字串(形如 {{key}}
)。如果對應的值是函式,則呼叫函式獲取結果進行替換,否則直接使用值進行替換。
接下來,定義了 generate
函式,它接受三個引數:title
、一個包含配置資訊的物件(包含 corpus
以及可選的 min
和 max
)。
在函式內部:
透過
randomInt
生成一個在min
和max
範圍內的文章長度articleLenth
。從
corpus
物件中解構出幾個部分,並對每個部分使用createRandomPicker
函式建立隨機選擇器。透過一個迴圈生成文章內容,每次迴圈生成一個段落。在生成段落的過程中,根據隨機數決定使用不同的句子生成方式,並透過
sentence
函式進行處理和組合。不斷累加段落的長度,直到總長度達到
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(''));
總結
希望看到這裏的你能夠有所收穫!!!!自己動手實現一個簡易的文章生成器吧
後期可以結合AI去實現更加智慧的文章生成器