切換語言為:簡體

Node.js實現一個文章生成器

  • 爱糖宝
  • 2024-07-04
  • 2074
  • 0
  • 0

前言

本文將從零開始,講解如何使用Node.js來實現一個文章生成器

node裡面有很多優秀的模組,現在我們就藉助node的fs模組來操控文字,來實現我們想要的效果

效果展示

Node.js實現一個文章生成器

  • 體驗 fs

首先我們先建立一個json檔案

Node.js實現一個文章生成器

裡面放一些內容

Node.js實現一個文章生成器

接下來我們書寫程式碼

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

Node.js實現一個文章生成器

可以看到我們就能讀取到檔案裡的資料,這裏我們體驗了fs裡面強大的功能

在這裏我們放了文章的一些必須點,如文章內容、標題等,透過隨機拿取資料生成一個文章

Node.js實現一個文章生成器

這裏我們透過

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 - 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 ,它的功能是:

  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 } = 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 )。

在函式內部:

  1. 透過 randomInt 生成一個在 min 和 max 範圍內的文章長度 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(''));

總結

希望看到這裏的你能夠有所收穫!!!!自己動手實現一個簡易的文章生成器吧

後期可以結合AI去實現更加智慧的文章生成器

0則評論

您的電子郵件等資訊不會被公開,以下所有項目均必填

OK! You can skip this field.