27

基于 Serverless 快速实现简单版查询工具

 4 years ago
source link: https://www.infoq.cn/article/oVdCaAOFMaIEJ4pj8WlO
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

朋友的单位有一个小型的图书室,图书室中摆放了很多的书,每本书都被编号放在对应的区域,为了让大家更快、更容易找到这些书,他联系我,让我帮他弄一个图书查询系统,通过用户输入能模糊匹配到对应的结果,并且提供书籍对应的地点。

功能设计

  • 让朋友把书籍整理并存储到一个 Excel 表格中;
  • 将 Excel 表放到对象存储中,云函数读取这个文件并解析;
  • 根据词语的相似寻找相似的图书;
  • 前端页面通过 MUI 制作,放在对象存储中,并且使用对象存储的 Website 功能;

整体实现

数据形态

Excel 样式主要包括书名和编号,同时下面包括分类的 tab:

qMJFnqz.png!web

基于函数的搜索功能

核心代码实现:

复制代码

importjieba
importopenpyxl
fromgensimimportcorpora, models, similarities
fromcollectionsimportdefaultdict
importurllib.request

withopen("/tmp/book.xlsx","wb")asf:
f.write(
urllib.request.urlopen("https://********").read()
)


top_str ="abcdefghijklmn"
book_dict = {}
book_list = []
wb = openpyxl.load_workbook('/tmp/book.xlsx')
sheets = wb.sheetnames
foreve_sheetinsheets:
print(eve_sheet)
sheet = wb.get_sheet_by_name(eve_sheet)
this_book_name_index =None
this_book_number_index =None
foreve_headerintop_str:
ifsheet[eve_header][0].value ==" 书名 ":
this_book_name_index = eve_header
ifsheet[eve_header][0].value ==" 编号 ":
this_book_number_index = eve_header
print(this_book_name_index, this_book_number_index)
ifthis_book_name_indexandthis_book_number_index:
this_book_list_len = len(sheet[this_book_name_index])
foriinrange(1, this_book_list_len):
add_key ="%s_%s_%s"% (
sheet[this_book_name_index][i].value, eve_sheet, sheet[this_book_number_index][i].value)
add_value = {
"category": eve_sheet,
"name": sheet[this_book_name_index][i].value,
"number": sheet[this_book_number_index][i].value
}
book_dict[add_key] = add_value
book_list.append(add_key)


defgetBookList(book, book_list):
documents = []
foreve_sentenceinbook_list:
tempData =" ".join(jieba.cut(eve_sentence))
documents.append(tempData)
texts = [[wordforwordindocument.split()]fordocumentindocuments]
frequency = defaultdict(int)
fortextintexts:
forwordintext:
frequency[word] +=1
dictionary = corpora.Dictionary(texts)
new_xs = dictionary.doc2bow(jieba.cut(book))
corpus = [dictionary.doc2bow(text)fortextintexts]
tfidf = models.TfidfModel(corpus)
featurenum = len(dictionary.token2id.keys())
sim = similarities.SparseMatrixSimilarity(
tfidf[corpus],
num_features=featurenum
)[tfidf[new_xs]]
book_result_list = [(sim[i], book_list[i])foriinrange(0, len(book_list))]
book_result_list.sort(key=lambdax: x[0], reverse=True)
result = []
foreveinbook_result_list:
ifeve[0] >=0.25:
result.append(eve)
returnresult


defmain_handler(event, context):
try:
print(event)
name = event["body"]
print(name)
base_html ='''<div class='mui-card'><div class='mui-card-header'>{{book_name}}</div><div class='mui-card-content'><div class='mui-card-content-inner'> 分类:{{book_category}}<br> 编号:{{book_number}}</div></div></div>'''
result_str =""
foreve_bookingetBookList(name, book_list):
book_infor = book_dict[eve_book[1]]
result_str = result_str + base_html.replace("{{book_name}}", book_infor['name']) \
.replace("{{book_category}}", book_infor['category']) \
.replace("{{book_number}}", book_infor['number']ifbook_infor['number']else"")
ifresult_str:
returnresult_str
exceptExceptionase:
print(e)
return'''<div class='mui-card' style='margin-top: 25px'><div class='mui-card-content'><div class='mui-card-content-inner'> 未找到图书信息,请您重新搜索。</div></div></div>'''

同时配置 APIGW:

ui67n2I.png!web

功能页面

复制代码

<!DOCTYPE html>
<html>
<head>
<metacharset="utf-8">
<title>图书检索系统</title>
<metaname="viewport"content="width=device-width, initial-scale=1,maximum-scale=1,user-scalable=no">
<metaname="apple-mobile-web-app-capable"content="yes">
<metaname="apple-mobile-web-app-status-bar-style"content="black">

<linkrel="stylesheet"href="https://others-1256773370.cos.ap-chengdu.myqcloud.com/booksearch/css/mui.min.css">
<style>
html,
body{
background-color:#efeff4;
}
</style>
<script>
functiongetResult(){
varUTFTranslate = {
Change:function(pValue){
returnpValue.replace(/[^\u0000-\u00FF]/g,function($0){
returnescape($0).replace(/(%u)(\w{4})/gi,"&#x$2;")
});
},
ReChange:function(pValue){
returnunescape(pValue.replace(/&#x/g,'%u').replace(/\\u/g,'%u').replace(/;/g,''));
}
};

varxmlhttp;
if(window.XMLHttpRequest) {
// IE7+, Firefox, Chrome, Opera, Safari 浏览器执行代码
xmlhttp =newXMLHttpRequest();
}else{
// IE6, IE5 浏览器执行代码
xmlhttp =newActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange =function(){
if(xmlhttp.readyState ==4&& xmlhttp.status ==200&& xmlhttp.responseText) {
document.getElementById("result").innerHTML = UTFTranslate.ReChange(xmlhttp.responseText).slice(1,-1).replace("\"",'"');
}
}
xmlhttp.open("POST","https://********",true);
xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xmlhttp.send(document.getElementById("book").value);
}
</script>
</head>
<body>
<divclass="mui-content"style="margin-top: 50px">
<h3style="text-align: center">图书检索系统</h3>
<divclass="mui-content-padded"style="margin: 10px; margin-top: 20px">
<divclass="mui-input-row mui-search">
<inputtype="search"class="mui-input-clear"placeholder=" 请输入图书名 "id="book">
</div>
<divclass="mui-button-row">
<buttontype="button"class="mui-btn mui-btn-numbox-plus"style="width: 100%"onclick="getResult()">检索
</button>  
</div>
</div>
<divid="result">
<divclass="mui-card"style="margin-top: 25px">
<divclass="mui-card-content">
<divclass="mui-card-content-inner">
可以在搜索框内输入书籍的全称,或者书籍的简称,系统支持智能检索功能。
</div>
</div>
</div>
</div>
</div>
<scriptsrc="https://others-1256773370.cos.ap-chengdu.myqcloud.com/booksearch/js/mui.min.js"></script>
</body>
</html>

效果展示

为了便于朋友使用,我将这个页面用 Webview 封装成一个 APP,整体效果如下:

e6r6Fve.png!web

总结

这是一个低频使用的 APP,如果是构建在传统服务器上,不是一个明智的选择,而云函数的按量付费,对象存储与 APIGW 的融合,完美解决了资源浪费的问题,同时借用云函数的 APIGW 触发器,可以很简单轻松的替代传统的 Web 框架和部分服务器软件的安装和使用、维护等。这个例子非常小,但却是一个有趣的小工具,除了图书查询之外,我们还可以继续拓展构建其它系统,例如成绩查询等。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK