<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          做一個(gè)刷題小程序

          共 9955字,需瀏覽 20分鐘

           ·

          2024-12-02 08:21

          今天為大家分享一篇比較有意思的文章,看看無所不能的程序員是如何滿足老婆的'刁鉆'需求的。^_^

          以下是正文:

          背景

          老婆:難道你不能將機(jī)構(gòu)的pdf的試卷,轉(zhuǎn)換成駕考寶典一樣的刷題程序嗎?

          我:女人你成功引起了我的注意,安排!巴啦啦能量,nodejs給我力量!

          今年考公、考編的人真的多。我的老婆也報(bào)名了社工(哈哈哈也算是個(gè)岸吧)。報(bào)了機(jī)構(gòu)最后都有很多份考前密卷,但是這些密卷基本上都是pdf。

          習(xí)慣了用類似駕考寶典一樣的刷題軟件,有錯(cuò)題集,有對(duì)應(yīng)解析。同時(shí)上班時(shí)間,晚上關(guān)燈,帶娃的時(shí)候都能刷題。

          需求分析

          基本需求

          • 客戶端 我需要一個(gè)客戶端接受試卷數(shù)據(jù),用駕考寶典的方式展示,答題后展示解析,答錯(cuò)進(jìn)入錯(cuò)題集。

          • 解析工具
            第二我需要一個(gè)解析工具將pdf快速轉(zhuǎn)成我需要的數(shù)據(jù)結(jié)構(gòu),提供給小程序使用。

          • ~?后端?~
            為了盡快使用,我們直接將生成的數(shù)據(jù)放在前端就好了,不然還要再開發(fā)一個(gè)端,同時(shí)會(huì)把這個(gè)事情做的越來越復(fù)雜。

          約定數(shù)據(jù)格式

          interface ExamProps {
              name: string// 考卷信息  
              type1 | 2 | 3// 1-綜合能力 2-法規(guī)政策 3-工作實(shí)務(wù)  
              score: number// 滿分  
              time: number// 考試時(shí)間,單位分鐘  
              question: {  
                  type1 | 2 | 3// 1-單選 2-多選 3-簡(jiǎn)答  
                  options: {label: string; value: number}[]; // 選項(xiàng)  
                  score: number// 分?jǐn)?shù)  
                  answer: number | number[] | string// A-1 B-2 C-3 D-4 E-5 F-6 G-7 H-8  
                  analysis?: string// 答案解析  
                  sort: number// 題目編號(hào)  
              }[]  
          }  

          不同端方案

          客戶端

          可選擇:H5/PC/小程序/APP

          什么端都行其實(shí),小程序和APP體驗(yàn)好一些,相對(duì)而言小程序安裝個(gè)人成本低。所以選擇小程序。

          將對(duì)方加入你個(gè)人小程序的開發(fā)者或者體驗(yàn)者就好了,也不需要上線。

          因?yàn)槲业目蛻舸笕诵枰氖鞘謾C(jī)刷題,如果你那邊是上班摸魚,選擇PC端最好

          解析工具

          • 方案一:手動(dòng)復(fù)制粘貼(臭不要臉!!!hetui)
          • 方案二:AI識(shí)別(不識(shí)別并羞辱了你??????)
          • 方案三:OCR技術(shù)(開整???)

          技術(shù)方案當(dāng)然選擇前端秘技——node.js(關(guān)鍵我也不會(huì)別的啊)

          PDF數(shù)據(jù)轉(zhuǎn)換

          實(shí)現(xiàn)思路

          • PDF解析成圖片輸出
          • 圖片文字識(shí)別后保存
          • 識(shí)別內(nèi)容轉(zhuǎn)成對(duì)應(yīng)格式

          和大象關(guān)進(jìn)冰箱里一樣簡(jiǎn)單??

          從需求到代碼

          PDF解析成圖片輸出

          使用node-poppler進(jìn)行pdf操作

          const { Poppler } = require('node-poppler');  
          const path = require('path');  
          const fs = require('fs');  
            
          // 創(chuàng)建 Poppler 實(shí)例  
          const poppler = new Poppler();  
          const pdfName = '1';  
          const filePath = path.join(__dirname, 'pdf'`${pdfName}.pdf`);  
          // 輸出圖片路徑目錄  
          const outputDir = path.join(__dirname, 'output'`${pdfName}pdf`);  
          const outputFilePath = path.join(outputDir, `page`);  
            
          const options = {  
              firstPageToConvert1,  
              lastPageToConvert1,  
              pngFiletrue,  
          };  
          await poppler.pdfToCairo(filePath, outputFilePath, options);  

          這樣我們就將指定頁面的pdf轉(zhuǎn)行成圖片了,但是這是出現(xiàn)了一個(gè)難點(diǎn)!

          難點(diǎn):答案頁,一張圖是左右排版的,ocr解析會(huì)有問題。

          如圖所示:

          所以需要對(duì)答案頁進(jìn)行裁剪保存輸出圖片,其實(shí)也簡(jiǎn)單

          • 先獲取總的頁面數(shù)量
          const pageCount = await getPdfPageCount(filePath);  
          • 規(guī)定需要裁剪的頁數(shù)
          const answerPage = 13 + 1// 封面 + 13頁(純?nèi)斯ぃ?nbsp; 
          • 裁剪函數(shù)

          先輸出圖片,然后使用jimp依賴進(jìn)行圖片裁剪

          const Jimp = require('jimp');  
            
          const cropImage = async (imagePath, pageIndex) => {  
          try {  
              const image = await Jimp.read(`${imagePath}-${pageIndex}.png`);  
              const halfWidth = Math.floor(image.bitmap.width / 2);  

              // 左半部分裁剪  
              await image  
                      .clone()  
                      .crop(00, halfWidth, image.bitmap.height)  
                      .writeAsync(path.join(outputDir, `page-${pageIndex}-1.png`));  

              // 右半部分裁剪  
              await image  
                      .clone()  
                      .crop(halfWidth, 0, halfWidth, image.bitmap.height)  
                      .writeAsync(path.join(outputDir, `page-${pageIndex}-2.png`));  

              console.log(`頁面 ${pageIndex} 裁剪成功`);  
              // 刪除原圖  
              fs.rmSync(`${imagePath}-${pageIndex}.png`)  
          catch (err) {  
              console.error(`頁面 ${pageIndex} 裁剪失敗:`, err);  
          }  
          };  
          • 循環(huán)輸出

          總結(jié):讀取pdf 頁數(shù),循環(huán)輸出每一頁的圖片,對(duì)答案解析頁進(jìn)行裁剪處理。

          這就是我們得到的圖片了:

          ### 圖片文字識(shí)別后保存

          因?yàn)镺CR是個(gè)直男,無差別識(shí)別,圖片上有什么文字都給你識(shí)別出來,不管你要不要(喊破喉嚨也沒用)。

          所以我去探究了一下有道云的智能識(shí)別,可以劃分題目的位置等等。探究了一下,并不是特別的好用,而且免費(fèi)額度比較少,用不起。

          不好用的點(diǎn):切分題目的只給位置信息不給題目信息,給信息的不切分。據(jù)我設(shè)想,需要根據(jù)位置信息,只能說需求沒對(duì)上吧~~~

          所以直男入選,那么這一步就很簡(jiǎn)單了,就是識(shí)別然后保存下來,下一步再解析。

          • 循環(huán)解析圖片并保存為json
          const fs = require('fs');  
          const path = require('path');  
          const pdfName = '1';  
          const url = 'https://api.textin.com/ai/service/v2/recognize';  
          const appId = 'testAppId';  
          const secretCode = 'testSecretCode';  
          // 圖片文件夾路徑  
          const inputDir = path.join(__dirname, `output/${pdfName}pdf`);  
          const outputDir = path.join(__dirname, `output/${pdfName}pdf`);  
            
          async function processImages({  
          const imageFiles = fs.readdirSync(inputDir).filter(file => /\.(jpg|jpeg|png|bmp)$/i.test(file));  
            
          let allResults = [];  
            
          for (const file of imageFiles) {  
              const imagePath = path.join(inputDir, file);  
              console.log(`Processing ${imagePath}...`);  
              // ocr識(shí)別  
              const itemList = await sendRequest(url, appId, secretCode, imagePath);  
              allResults = allResults.concat(itemList?.map(item=> item.text));  
          }  
            
          // 將結(jié)果保存為 JSON 文件  
          const outputFilePath = path.join(outputDir, 'result.json');  
            
          fs.writeFileSync(outputFilePath, JSON.stringify(allResults, null2));  
          console.log(`All results saved to ${outputFilePath}`);  
          }  

          得到的數(shù)據(jù)如圖所示

          • ocr對(duì)接
            用的是textin的ocr技術(shù)

          • 發(fā)送請(qǐng)求解析圖片

          async function sendRequest(url, appId, secretCode, imagePath{  
          try {  
              const image = fs.readFileSync(imagePath);  
              const response = await axios.post(url, image, {  
                  headers: {  
                      'Content-Type''application/octet-stream',  
                      'x-ti-app-id': appId,  
                      'x-ti-secret-code': secretCode  
                  }  
              });  

              if (response.status === 200) {  
                  const ret = response.data;  
                  return ret.result ? ret.result.lines : [];  
              } else {  
                  console.error(`Request failed with status code ${response.status}`);  
                  return [];  
              }  
          catch (error) {  
              console.error('Request failed:', error);  
              return [];  
          }  
          }  

          總結(jié):我們已經(jīng)將pdf轉(zhuǎn)成圖片并且識(shí)別到了圖片中的所有文字(勝利在望)

          最后一步我們就需要處理這些文字了

          首先我們要發(fā)覺這些文字的規(guī)律,還有其中多余的文字,以及如何解析出題目、選項(xiàng)、關(guān)聯(lián)答案(答案是分開的)

          規(guī)律如下:

          • 1.去掉,${number}頁第${number}頁這樣的文字
          • 2.匹配到""參考答案"后進(jìn)入答案解析部分
          • 3.每個(gè)題目前面都有序號(hào),選項(xiàng)在兩個(gè)題目之間
          • 4.每個(gè)答案前面都有序號(hào),與題目序號(hào)相同

          把這些規(guī)律交給GPT,讓GPT幫你寫一段解析代碼,輸出你想要的格式,這樣就大功告成了,

          客戶端對(duì)各位大佬都是灑灑水啦就不班門弄斧了。

          最后效果是這樣的:

          image.png

          這UI設(shè)計(jì)真是簡(jiǎn)約而不簡(jiǎn)單呢,哈哈哈

          原文:https://juejin.cn/post/7397588804825022518

          作者:可汗


          瀏覽 50
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  天天日天天射一区二区三区 | 精品无码秘 人妻一区二区三区 | 亚洲综合无码一区二区毛片 | 免费视频久久久 | 日韩日韩日韩日韩AV |