专栏首页fanzhh的技术笔记使用Sqlite3+Express.js+React实现在线答题(上)

使用Sqlite3+Express.js+React实现在线答题(上)

将word格式的题库转为txt格式,导入至sqlite3中,使用Express.js做服务端提供json格式数据,使用React做前端获取服务端数据。本文为第一部分,实现导入数据和服务端提供数据API接口。

数据导入

源格式

源题库为word格式,题型分别为单选、多选和判断题。

单选题

多选题

判断题

转为txt格式

为便于读取,word格式另存为txt格式,文件名为questions.txt

建立数据库

我使用的IPython来建立数据库:

import sqlite3
conn=sqlite3.connect('mydb.db')
c=conn.cursor()
c.execute('''create table (
                 id int primary key, // 主键 
                 description text,  // 题目
                 answer text,  // 答案
                 A text, //选择项A。判断题时,A为正确。
                 B text, //选择项B。判断题时,B为错误。
                 C text, //选择项C
                 D text, //选择项D
                 E text, //选择项E。默认最多5个选择项。
             )''')
c.commit()

从txt文件中提取试题信息

txt题库中,每道题都以阿拉伯数字+.开始,形如1.,选择题题干中正确答案在全角括号中,形如(ABCD),判断题题干行中会有×符合,据此提取数据。代码如下:

import re // 导入正则表达式模块
p1=re.compile("\d+.")  // 判断是否为新的题干的正则表达式
p2=re.compile("((.+))") // 提取正确答案的正则表达式
f=open('questions.txt','r') // 打开文本文件
lines=f.readlines()  // 读取全部文本
questions = [] // 建立空题库,在遍历文本中追加
description='' // 初始化题目
answer='' // 初始化答案
A='' // 初始化选项
B=''
C=''
D=''
E=''
for line in lines:
    if p1.match(s): // 该行以数字+.开始,遇到一道新题
        if description != '': // 确定题目非空
            questions.append([description,answer,answerA,   // 新题追加到题库中,
                answerB,answerC,answerD,answerE,remark])
        question=''  // 然后清空各字段
        answer=''
        answerA=''
        answerB=''
        answerC=''
        answerD=''
        answerE=''
        remark=''
        if '×' in s or '√' in line: // 这是一道判断题吗
                description=s[:s.find('(')] // 提取题目表述
                answerA='√'
                answerB='×'
                remark='2' // 为便于排序,备注中判断题标记为2
                if '×' in s:  // 答案为×
                    answer='B'
                elif '√' in s:
                    answer='A'
                continue // 判断题没有选择项,所以直接跳到下一个循环
        else: // 不是判断,那就是选择题了
                  description=s[:s.find('(')+1]+s[s.find(')'):] // 提取题目描述
                  answer=p2.search(s).group(1).strip()
                  if len(answer)>1:
                       remark='1' // 多选题标记为1
                  else:
                       remark='0' // 单选题标记为0
    else: // 该行不是以数字+.开始,是选择项
        answers = s.split() // 选择项之间以空格分开
        for an in answers:
            if an.startswith('A'): // 选项A
                answerA=an
            elif an.startswith('B'): // 选项B
                answerB=an
            elif an.startswith('C'): // 选项C
                answerC=an
            elif an.startswith('D'): // 选项D
                answerD=an 
            elif an.startswith('E'): // 选项E
                      answerE=an

试题信息导入数据库

现在,所有题目都在questions数组中,可以插入到数据库中了:

conn = sqlite3.connect('mydb.db') // 连接数据库
c=conn.cursor()  // 获取游标
i=1 // 计数器,做ID赋值用
for q in questions:
    // 执行插入
    c.execute("insert into question(id,description,answer,A,B,C,D,E,remark) values(%d,'%s','%s','%s','%s','%s','%s','%s','%s')"%(i,q[0],q[1],q[2],q[3],q[4],q[5],q[6],q[7]))                                                 
    i=i+1
conn.commit() // 提交

使用express.js建立服务端

新建目录express-sqlite3:

$ mkdir express-sqlite3 ; cd express-sqlite3

建立新文件package.json,输入以下内容:

{
  "name": "express-sqlite3",
  "version": "1.0.0",
  "description": "",
  "main": "restapi.js",
  "dependencies": {
    "express": "^4.13.1",
    "sqlite3": "https://github.com/mapbox/node-sqlite3/tarball/master"
  },
  "devDependencies": {},
  "scripts": {
    "start": "node restapi.js"
  },
  "author": "",
  "license": "ISC"
}

执行npm install安装包。 新建db目录,将上一步生成的mydb.db文件拷贝至此目录内。 新建restapi.js文件,输入以下内容:

var sqlite3 = require('sqlite3').verbose();
var db = new sqlite3.Database('db/mydb.db');

var express = require('express');
var restapi = express();

restapi.get('/data', function(req, res){
    results = [];
    db.all("SELECT * from question order by remark,description", function(err, rows){
        rows.map((row)=>{
        results.push({"id":row.id,
                  "description":row.description,
                  "answer":row.answer,
                  "A":row.A,
                  "B":row.B,
                  "C":row.C,
                  "D":row.D,
                  "E":row.E,
                  "remark":row.remark,})
        });
        res.json(results);
    });
});

restapi.listen(3000); // 在3000端口监听

console.log("Submit GET to http://localhost:3000/data");

在命令行执行:

npm start
> express-sqlite3@1.0.0 start /home/fanzhh/projects/express-sqlite3
> node restapi.js
Submit GET to http://localhost:3000/data

此时在浏览器输入地址http://localhost:3000/data,页面显示如下:

json数据

OK。下一章我们将用React实现前端的在线答题。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 使用docker封装古董web.py+postgresql应用

    title: 使用docker封装古董python web.py + postgresql应用 author: fanzhh category: - 技术...

    fanzhh
  • Keras 初学者教程:使用python了解深度学习

    我们将训练一个手写数字识别分类器,其在著名的MNIST数据集上将具有超过99%的准确率。

    fanzhh
  • Django Rest Model 中 User 字段的插入问题

    百思不得其解,因为明明通过creater=self.request.user赋值了啊。 后来在Model中,将creater字段修改为

    fanzhh
  • 50行代码实现GAN | 干货演练

    2014年,Ian Goodfellow和他的同事发表了一篇论文,向世界介绍了生成对抗网络(GAN)。通过对计算图和博弈论的创新性组合,他们表明如果有足够的建模...

    磐创AI
  • 代码也是可以很优美

    昨天在技术交流群,有位读者吐槽刚刚接手的代码(文章标题),代码全篇无格式,无注释,多个嵌套不打括号,函数命名不规范,代码实在看不下去。随着软件项目代码的日积月累...

    Java团长
  • 多用多学之Java中的Set,List,Map

            很长时间以来一直代码中用的比较多的数据列表主要是List,而且都是ArrayList,感觉有这个玩意就够了。ArrayList是用于实现动态数组...

    用户1105954
  • Fibonacci

    斐波那契数列(Fibonacci sequence),又称黄金分割数列、因[数学家]列昂纳多·斐波那契(Leonardoda Fibonacci)以兔子繁殖为例...

    AngelNH
  • 网络字体反爬之起点中文小说

    前几天跟同事聊到最近在看什么小说,想起之前看过一篇文章说的是网络十大水文,就想把起点上的小说信息爬一下,搞点可视化数据看看。这段时间正在看爬虫框架-pyspid...

    星星在线
  • 面试汇总(一):针对百度面试总结

      首先跟大家说声抱歉,由于最近有面试和笔试,所以一直刷题就没时间更新博客了。随着秋招进入了一个白热化阶段,我们所投的岗位也已经进入了面试阶段。就昨天第一次面试...

    stefan666
  • Pytorch深度学习实战教程(四):必知必会的炼丹法宝

    我们不可能像「太上老君」那样,拿着浮尘,24 小时全天守在「八卦炉」前,更何况人家还有炼丹童、天兵天将,轮流值守。

    Jack_Cui

扫码关注云+社区

领取腾讯云代金券