将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
> [email protected] start /home/fanzhh/projects/express-sqlite3
> node restapi.js
Submit GET to http://localhost:3000/data
此时在浏览器输入地址http://localhost:3000/data
,页面显示如下:
OK。下一章我们将用React
实现前端的在线答题。