SEU_scheduleV1.0
特殊時期,被迫宅在家中無所事事,就想學一下簡單的後端,搭建一個數據庫。
現在把搭建過程記錄一下,也算一個小型數據庫的搭建教程。
SEU_scheduleV1.0:http://byzeal.cn/SEU/SEU_schedule.html
SEU_scheduleV1.0:http://49.232.58.172/SEU/SEU_schedule.html
(由於2020.2.13前新域名都在備案,所以給出服務器地址吧qwq)
這是一個小工具,把學校課程做成數據庫,前端做成了動態表格,實現了查詢、分頁、篩選的功能
思路概括
一個好的網頁項目,需要有舒適體驗的前端以及不掉鏈子的後端。之前不管是寫自己的主頁還是在csdn上寫博客,不管是html還是md,我的體驗都侷限於靜態頁面,從未接觸過真正的數據庫。所以這次我把重點放在了研究後端上,在開始寫網頁前,查了很多關於數據庫的資料,最終確定了自己的數據庫形式。
總的來說,就是搭建前臺,前臺做好response和request響應;搭建後臺,將需要的數據導入數據庫;再寫好數據庫及其接口,使其能處理response和request;接下來,在接口的基礎上寫一些處理不同request的函數,比如搜索引擎,分頁算法等等;最後,做一些潤色工作,使網頁體驗更加舒適。當然,在每一步的嘗試中,我都遇到了很多困難,換了很多種不同的實現方法。開始嘗試了mysql、mongodb、lowdb等等,後來不斷遇到問題不斷換思路,東拼西湊了一堆方法方法最終實現了這個小工具(最終是用layui+nodejs+json小數據庫實現)。
實現過程
1.爬取數據
選擇你想要爬取數據的來源,我選擇的是學校的教務處網站
SEU教務處的數據服務地址:http://xk.urp.seu.edu.cn/jw_service
注意:爬取數據的網址儘量選一些校園網,公益教育網之類的,不然處理繁雜的數據也不是一件易事。
基於python urllib和request包,從服務器中爬取數據,具體細節就不說了,這並不是重點。
有趣的是,在爬取數據的過程中,意外的發現在服務器中竟然存在着靜態的數據文件。所以沒花多長時間就搞到了全校的課程數據。之後數據可以選擇先保存成txt(注意編碼,不是utf-8可能之後會出現漢字亂碼問題),也可以用pandas轉成excel(我轉成了excel),方便之後的轉化。
2.處理數據:excel數據與json數據轉換
.json是很多數據庫與前端交換數據的文件形式,我們可以先將上一步爬到的數據變成json文件
這裏介紹一個很好的轉換工具http://excel.wj2015.com/,提供layui數據格式轉換。由於我確定要使用layui完成前端,所以在轉換完成後格式上不需要更改。如果你使用別的數據格式,根據data[]數組進行修改即可。
layui數據格式:
如果只保留data數組:
在數據對象中A屬性我設置成了編號,想着之後檢索快一點(事實證明似乎沒有卵用 )
3.後端準備:選擇數據接口
有什麼方便的,不需要新學動態網頁語言的,操作簡單的數據接口搭建方式嗎?有的!!!就是nodejs!!!
百度百科是這麼描述它的:
Node 是一個讓 JavaScript 運行在服務端的開發平臺,它讓 JavaScript 成爲與PHP、Python、Perl、Ruby
等服務端語言平起平坐的腳本語言。
完全不需要接觸php,在nodejs的運行環境中,你可以輕鬆的用JavaScript 搭建自己的數據接口。
安裝與配置nodejs的教程在這裏:nodejs
安裝完nodejs後,其實還需要安裝一堆擴展包,後面都會用到。這裏我就先總結一下
需要:express、body、cors
npm install -g express –registry=https://registry.npm.taobao.org
它們安裝都在cmd終端,指令格式可以參考上條語句
nodejs本體和擴展包都安裝完了就可以開始工作了
先做一個服務器測試,新建test.js腳本
var express = require("express");
var app = express();
app.listen(3000);
app.get("/",function(req,res){
res.send("第一個本地服務器");
});
終端執行
node test.js
用瀏覽器打開127.0.0.1:3000
測試成功
接下來就是搭建數據接口了
這裏給出我做好的數據接口
const express=require('express');
const cors=require('cors');
const app=express();
app.listen(7979,()=>console.log('server start'));
app.use(cors());
app.all('*', (req, res) =>
{
console.log(req.query);
console.log(req.query.page);
res.json("這裏是你想要返回給前臺的數據");
}
});
cors=require(‘cors’) 必須要用,跨域訪問,這就是之前需要安裝的擴展包,我在這卡了好長時間T^T,沒有它訪問就是空白
app.listen(7979)表示監聽7979端口,這個任意設置,只要不與你的服務器上其他端口重合就行
console.log(req.query) 用於在cmd上顯示日誌,合理添加一些console.log可以方便地掌握數據交換全過程
res.json() 以json文件形式返回,res共有三種,詳情見nodejs的api文檔
日誌信息
4.前端html設計
選擇layui框架來做表格,用了一次過於上癮,甚至以後所有的博客都想用layui寫
給出表格框框的代碼
function tablefun(_table, _type, _data) {
_table.render({
elem: '#type' + _type
, data: _data
, page: true
, toolbar: '<div><b style="color:#009688">2019-2020-3</b></div>'
, defaultToolbar: []
, cols: [[
{field:'B', title: '課程名', width:200, sort: true}
,{field:'C', title: '面向年級', width:120,sort: true}
,{field:'D', title: '任課教師', width:120}
,{field:'E', title: '上課安排', width:350}
,{field:'F', title: '開設院系', width:230,sort: true}
,{field:'point', title: '學分', width: 100}
]],
text: {
none: '沒有查到想要的課程(T^T),縮小關鍵詞試試?'
}
});
}
因爲我需要分頁和搜索的功能,所以我單寫了一個table函數出來,如果只是官方標準表格的話,用一個簡單的渲染就可以了
上述代碼實現效果
搜索框的實現代碼
<div class="layui-form-item">
<label class="layui-form-label">課程名:</label>
<div class="layui-input-block">
<input type="text" class="layui-input layui-input-wide" name="B" placeholder="課程關鍵詞,eg:計算機科學基礎Ⅱ" autocomplete="off">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">任課教師:</label>
<div class="layui-input-block">
<input type="text" class="layui-input layui-input-wide" name="D" placeholder="需查詢的姓名,eg:萬國瑞" autocomplete="off">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">時間/地點:</label>
<div class="layui-input-block">
<input type="text" class="layui-input layui-input-wide" name="E" placeholder="查詢時間或者地點,eg:週五 或 教八" autocomplete="off">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">開課學院:</label>
<div class="layui-input-block">
<select name="F" >
<option value=""></option>
<option value="教務處">教務處</option>
<option value="[01]建築">[01]建築</option>
//這裏是一堆選擇,按照自己需求添加
<option value="[TJ]工科試驗班 (土木交通類)">[TJ]工科試驗班 (土木交通類)</option>
</select>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label"></label>
<div class="layui-input-inline">
<button class="layui-btn" lay-submit lay-filter="search">查詢</button>
<button type="reset" class="layui-btn layui-btn-primary" onclick="ResetSearch()">重置</button>
</div>
</div>
</form>
搜索框的實現效果
5.實現前端到後端數據傳遞:$.ajax和request
由於我設想的功能是搜索和數據分頁顯示,所以我需要構建兩個請求
對於分頁的請求:layui表格模塊自己有一個request請求參數,向後臺返回用戶選擇要看第幾頁和頁面大小兩個參數(詳情見layui文檔),在後臺捕捉就可以了。
對於搜索的請求:這其實就是一般化的前端請求,我們需要用$.ajax發送
在網頁中引入jquery
<head>
<script src="https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js">
</script>
</head>
建議使用百度鏡像,現存的版本都比較穩定
$.ajax請求格式如下(這不是網頁中源碼,網頁中ajax很簡陋,這裏放一個完整版ajax看得更清楚一點)
關於 $.ajax具體配置這裏有詳細解釋:ajax
$(function(){
$('#send').click(function(){
$.ajax({
type: "GET",
url: "test.json",
data: {username:$("#username").val(), content:$("#content").val()},
dataType: "json",
success: function(data){
$('#resText').empty(); //清空resText裏面的所有內容
var html = '';
$.each(data, function(commentIndex, comment){
html += '<div class="comment"><h6>' + comment['username']
+ ':</h6><p class="para"' + comment['content']
+ '</p></div>';
});
$('#resText').html(html);
}
});
});
});
6.實現自己的搜索引擎&分頁算法
這部分是最肝的地方,需要設計一些算法。因爲沒有學過js,很多處理數據的函數都不太會用,所以每寫一點都要查好多資料,最後的實現函數寫得也不是很好,回過來再看簡直是一坨屎山 ,以後慢慢再修改算法吧······
先是分頁算法:
function pagination(page, limit, array) {
offset = (page - 1) * limit;
return array.slice(offset, offset + limit);
}
function pagetest(a,b,c){
arr2 = pagination(a,b,c);
ob2 = {"code":0,"msg":"","count":3206,"data":arr2};
return ob2;
}
這兩個函數第一個是核心,根據前臺傳過來的兩個參數page limit確定需要發送的數據;第二個函數則是將確定要發送的數據封裝成layui表格可以接受的形式。
注意count:3206這一句是數據條數,因爲我的數據不會變所以直接寫出來,數據條數變時需要改成數據數組的長度
然後是搜索算法:
for (i in AllData) {
var flag = true;
if (gtype > 0) {
flag &= AllData[i].t_type == gtype;
}
if (last_param['B'] != '') {
flag &= (AllData[i].B||"").toLowerCase().indexOf(last_param['B'].toLowerCase()) > -1;
}
if (last_param['D'] != '') {
flag &= (AllData[i].D||"").toLowerCase().indexOf(last_param['D'].toLowerCase()) > -1;
}
if (last_param['E'] != '') {
flag &= (AllData[i].E||"").toLowerCase().indexOf(last_param['E'].toLowerCase()) > -1;
}
if (last_param['F'] != '') {
flag &= (AllData[i].F||"").toLowerCase().indexOf(last_param['F'].toLowerCase()) > -1;
}
if (flag) tmpData.push(AllData[i]);
}
這個剛開始封裝成函數了,後來修改了一堆自己也搞不清了,就單拎出來核心算法好了。alldata經過B D E F的限制最後得到tmpdata爲搜索後篩選出來的數據。
講道理,一個普通的模糊搜索算法應該不是很難,但是因爲不熟悉各種字符串、對象的操作,這裏耽誤了不少時間。
這些函數都可以在JavaScript文檔中找到,沒有什麼特別需要注意的。
簡單給出描述:
toLowerCase() 用於把字符串轉換爲小寫
indexOf() 可返回某個指定的字符串值在字符串中首次出現的位置,沒有查到就返回-1,老親切的形式了,業界規矩
7.收尾:潤色移動端轉碼
上述工作全部串起來,再自己寫寫頁面,基本就完工了。
我的頁面整體佈局是這樣
PC端的體驗還算良好,然後去試一下移動端(自己手機有問題還找同學的手機進行調試T^T)
發現頁面是這樣的
發現手機上完全按照PC端的格式顯示出來了,而手機屏幕小可能沒有辦法看清楚課程信息,所以就想着能不能讓屏幕網頁自適應屏幕大小。查了一些資料,發現< meta >就可以實現layui的自適應。
只需在網頁中加入這句話
< meta name=“viewport” content=“width=device-width, initial-scale=1, maximum-scale=1”>
加入後網頁效果:
okk這樣移動端的優化就做完啦,到此第一版SEU_schedule就全部完工了。以後還會不定時更新一下(ノ゚▽゚)ノ(maybe )