友的单位有一个小型的图书室,图书室中摆放了很多的书,每本书都被编号放在对应的区域,为了让大家更快、更容易找到这些书,他联系我,让我帮他弄一个图书查询系统,通过用户输入能模糊匹配到对应的结果,并且提供书籍对应的地点。
Excel 样式主要包括书名和编号,同时下面包括分类的 tab:
核心代码实现:
复制代码已复制
import jiebaimport openpyxlfrom gensim import corpora, models, similaritiesfrom collections import defaultdictimport urllib.request with open("/tmp/book.xlsx", "wb") as f: f.write( urllib.request.urlopen("https://********").read() ) top_str = "abcdefghijklmn"book_dict = {}book_list = []wb = openpyxl.load_workbook('/tmp/book.xlsx')sheets = wb.sheetnamesfor eve_sheet in sheets: print(eve_sheet) sheet = wb.get_sheet_by_name(eve_sheet) this_book_name_index = None this_book_number_index = None for eve_header in top_str: if sheet[eve_header][0].value == " 书名 ": this_book_name_index = eve_header if sheet[eve_header][0].value == " 编号 ": this_book_number_index = eve_header print(this_book_name_index, this_book_number_index) if this_book_name_index and this_book_number_index: this_book_list_len = len(sheet[this_book_name_index]) for i in range(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) def getBookList(book, book_list): documents = [] for eve_sentence in book_list: tempData = " ".join(jieba.cut(eve_sentence)) documents.append(tempData) texts = [[word for word in document.split()] for document in documents] frequency = defaultdict(int) for text in texts: for word in text: frequency[word] += 1 dictionary = corpora.Dictionary(texts) new_xs = dictionary.doc2bow(jieba.cut(book)) corpus = [dictionary.doc2bow(text) for text in texts] 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]) for i in range(0, len(book_list))] book_result_list.sort(key=lambda x: x[0], reverse=True) result = [] for eve in book_result_list: if eve[0] >= 0.25: result.append(eve) return result def main_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 = "" for eve_book in getBookList(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'] if book_infor['number'] else "") if result_str: return result_str except Exception as e: 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:
复制代码已复制
<!DOCTYPE html><html><head> <meta charset="utf-8"> <title> 图书检索系统 </title> <meta name="viewport" content="width=device-width, initial-scale=1,maximum-scale=1,user-scalable=no"> <meta name="apple-mobile-web-app-capable" content="yes"> <meta name="apple-mobile-web-app-status-bar-style" content="black"> <link rel="stylesheet" href="https://others-1256773370.cos.ap-chengdu.myqcloud.com/booksearch/css/mui.min.css"> <style> html, body { background-color: #efeff4; } </style> <script> function getResult() { var UTFTranslate = { Change: function (pValue) { return pValue.replace(/[^\u0000-\u00FF]/g, function (><!DOCTYPE html><html><head> <meta charset="utf-8"> <title> 图书检索系统 </title> <meta name="viewport" content="width=device-width, initial-scale=1,maximum-scale=1,user-scalable=no"> <meta name="apple-mobile-web-app-capable" content="yes"> <meta name="apple-mobile-web-app-status-bar-style" content="black"> <link rel="stylesheet" href="https://others-1256773370.cos.ap-chengdu.myqcloud.com/booksearch/css/mui.min.css"> <style> html, body { background-color: #efeff4; } </style> <script> function getResult() { var UTFTranslate = { Change: function (pValue) { return pValue.replace(/[^\u0000-\u00FF]/g, function ($0) { return escape($0).replace(/(%u)(\w{4})/gi, "$2;") }); }, ReChange: function (pValue) { return unescape(pValue.replace(//g, '%u').replace(/\\u/g, '%u').replace(/;/g, '')); } }; var xmlhttp; if (window.XMLHttpRequest) { // IE7+, Firefox, Chrome, Opera, Safari 浏览器执行代码 xmlhttp = new XMLHttpRequest(); } else { // IE6, IE5 浏览器执行代码 xmlhttp = new ActiveXObject("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><div class="mui-content" style="margin-top: 50px"> <h3 style="text-align: center"> 图书检索系统 </h3> <div class="mui-content-padded" style="margin: 10px; margin-top: 20px"> <div class="mui-input-row mui-search"> <input type="search" class="mui-input-clear" placeholder=" 请输入图书名 " id="book"> </div> <div class="mui-button-row"> <button type="button" class="mui-btn mui-btn-numbox-plus" style="width: 100%" onclick="getResult()"> 检索 </button> </div> </div> <div id="result"> <div class="mui-card" style="margin-top: 25px"> <div class="mui-card-content"> <div class="mui-card-content-inner"> 可以在搜索框内输入书籍的全称,或者书籍的简称,系统支持智能检索功能。 </div> </div> </div> </div></div><script src="https://others-1256773370.cos.ap-chengdu.myqcloud.com/booksearch/js/mui.min.js"></script></body></html><) { return escape(><!DOCTYPE html><html><head> <meta charset="utf-8"> <title> 图书检索系统 </title> <meta name="viewport" content="width=device-width, initial-scale=1,maximum-scale=1,user-scalable=no"> <meta name="apple-mobile-web-app-capable" content="yes"> <meta name="apple-mobile-web-app-status-bar-style" content="black"> <link rel="stylesheet" href="https://others-1256773370.cos.ap-chengdu.myqcloud.com/booksearch/css/mui.min.css"> <style> html, body { background-color: #efeff4; } </style> <script> function getResult() { var UTFTranslate = { Change: function (pValue) { return pValue.replace(/[^\u0000-\u00FF]/g, function ($0) { return escape($0).replace(/(%u)(\w{4})/gi, "$2;") }); }, ReChange: function (pValue) { return unescape(pValue.replace(//g, '%u').replace(/\\u/g, '%u').replace(/;/g, '')); } }; var xmlhttp; if (window.XMLHttpRequest) { // IE7+, Firefox, Chrome, Opera, Safari 浏览器执行代码 xmlhttp = new XMLHttpRequest(); } else { // IE6, IE5 浏览器执行代码 xmlhttp = new ActiveXObject("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><div class="mui-content" style="margin-top: 50px"> <h3 style="text-align: center"> 图书检索系统 </h3> <div class="mui-content-padded" style="margin: 10px; margin-top: 20px"> <div class="mui-input-row mui-search"> <input type="search" class="mui-input-clear" placeholder=" 请输入图书名 " id="book"> </div> <div class="mui-button-row"> <button type="button" class="mui-btn mui-btn-numbox-plus" style="width: 100%" onclick="getResult()"> 检索 </button> </div> </div> <div id="result"> <div class="mui-card" style="margin-top: 25px"> <div class="mui-card-content"> <div class="mui-card-content-inner"> 可以在搜索框内输入书籍的全称,或者书籍的简称,系统支持智能检索功能。 </div> </div> </div> </div></div><script src="https://others-1256773370.cos.ap-chengdu.myqcloud.com/booksearch/js/mui.min.js"></script></body></html><).replace(/(%u)(\w{4})/gi, "") }); }, ReChange: function (pValue) { return unescape(pValue.replace(//g, '%u').replace(/\u/g, '%u').replace(/;/g, '')); } }; var xmlhttp; if (window.XMLHttpRequest) { // IE7+, Firefox, Chrome, Opera, Safari 浏览器执行代码 xmlhttp = new XMLHttpRequest(); } else { // IE6, IE5 浏览器执行代码 xmlhttp = new ActiveXObject("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><div class="mui-content" style="margin-top: 50px"> <h3 style="text-align: center"> 图书检索系统 </h3> <div class="mui-content-padded" style="margin: 10px; margin-top: 20px"> <div class="mui-input-row mui-search"> <input type="search" class="mui-input-clear" placeholder=" 请输入图书名 " id="book"> </div> <div class="mui-button-row"> <button type="button" class="mui-btn mui-btn-numbox-plus" style="width: 100%" onclick="getResult()"> 检索 </button> </div> </div> <div id="result"> <div class="mui-card" style="margin-top: 25px"> <div class="mui-card-content"> <div class="mui-card-content-inner"> 可以在搜索框内输入书籍的全称,或者书籍的简称,系统支持智能检索功能。 </div> </div> </div> </div></div><script src="https://others-1256773370.cos.ap-chengdu.myqcloud.com/booksearch/js/mui.min.js"></script></body></html>
为了便于朋友使用,我将这个页面用 Webview 封装成一个 APP,整体效果如下:
这是一个低频使用的 APP,如果是构建在传统服务器上,不是一个明智的选择,而云函数的按量付费,对象存储与 APIGW 的融合,完美解决了资源浪费的问题,同时借用云函数的 APIGW 触发器,可以很简单轻松的替代传统的 Web 框架和部分服务器软件的安装和使用、维护等。这个例子非常小,但却是一个有趣的小工具,除了图书查询之外,我们还可以继续拓展构建其它系统,例如成绩查询等。
关注我并转发此篇文章,私信我“领取资料”,即可免费获得InfoQ价值4999元迷你书!
MLHttpRequest(oXMLHttpRequest) 对象属性
onreadystatechange 状态改变的事件触发器,只写;
XMLHttpRequest.onreadystatechange = funcMyHandler;
readyState 对象状态(integer),只读;
XMLHttpRequest.readyState;
0 = 未初始化 1 = 初始化 2 = 已发送 3 = 已接收部分数据 4 = 完成
0 (未初始化) 对象已建立, 但是尚未初始化---创建ajax对象(new XMLHttpRequest)
1 (初始化) 对象已初始化, 尚未调用send方法---初始化ajax对象(xmlHttp.open())
2 (发送数据) send方法已调用, 但是当前的状态及http头未知----发送请求(xmlHttp.send())
3 (数据传送中) 已接收部分数据, 因为响应及http头不全, 这时通过responseBody和responseText获取部分数据会出现错误,
4 (完成) 数据接收完毕, 此时可以通过通过responseBody和responseText获取完整的回应数据
responseText 服务器进程返回数据的文本版本,只读;(text/html)
strValue = XMLHttpRequest.responseText;(text/html)
strXML = XMLHttpRequest.responseXML;(text/xml)
status 服务器返回的状态码, 如:404 = "文件末找到" 、200 ="成功"
XMLHttpRequest.status;
常用的值有:
200 表示请求成功
202 表示被接收
400 表示错误的请求
404 表示资源未找到
500 表示内部服务器错误, 如php代码错误等
statusText 服务器返回的状态文本信息,如:ok、not found
strValue = XMLHttpRequest.statusText;
Ajax引擎对象中的方法
abort() 停止当前请求
XMLHttpRequest.abort();
getAllResponseHeaders() 作为字符串返回完整的headers
strValue = XMLHttpRequest.getAllResponseHeaders();
getResponseHeader() 作为字符串返回单个的header标签
strValue = XMLHttpRequest.getResponseHeader();
如:XMLHttpRequest.getResponseHeader("Server")
open("method","URL"[,asyncFlag[,"userName"[, "password"]]]) 设置未决的请求的目标 URL,方法,和其他参数
method:http方法, 例如:POST、GET、PUT及PROPFIND。大小写不敏感。
URL:请求的URL地址,可以为绝对地址也可以为相对地址。
asyncFlag[可选]:布尔型,指定此请求是否为异步方式,默认为true。如果为真, 当状态改变时会调用onreadystatechange属性指定的回调函数。
异步:同一个时间点允许执行多个进程。(true)
同步:同一个时间点只允许执行一个进程。(false)
userName[可选]:如果服务器需要验证,此处指定用户名,如果未指定,当服务器需要验证时,会弹出验证窗口。
password[可选]:验证信息中的密码部分,如果用户名为空,则此值将被忽略。
send(content) 发送请求
只有当ajax对象的send方法被调用时,才会发送请求
注意:
使用get将数据传给服务器,则服务器就使用$_GET
就直接通过url将数据传给服务器,发送请求使用send(null)语句
使用POST时一定要使用 xmlHttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
发送请求使用send(url)语句;
通常在数据不多的时候才有GET方式,而数据量稍大的时候采用POST方式
setRequestHeader("header", "value") 设置header并和请求一起发送
xmlHttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
完整实例:
<!DOCTYPE html>
<html>
<head>
<title>XMLHttpRequest</title>
<script language="javascript">
var xmlHttp;
function createXMLHttpRequest(){
if(window.ActiveXObject)
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
else if(window.XMLHttpRequest)
xmlHttp = new XMLHttpRequest();
}
function startRequest(){
createXMLHttpRequest();
var sUrl = "sync.php?" + new Date().getTime(); //地址不断的变化,解决IE缓存问题
xmlHttp.onreadystatechange = function(){
if(xmlHttp.readyState == 4 && xmlHttp.status == 200)
alert("服务器返回: " + xmlHttp.responseText);
}
xmlHttp.open("GET",sUrl,true);
xmlHttp.send(null);
}
</script>
</head>
<body>
<input type="button" value="测试异步通讯" onClick="startRequest()">
</body>
</html>
服务器端代码(文件名:sync.php)
<?php
header('Content-type: text/html;charset=utf-8');
echo "异步测试成功,很高兴";
?>
服务器端在返回数据时可不可以使用return代替echo?
答:不可以
原因如下:虽然return与echo都有返回的含义, 但是两者有很大的区别。return代表返回数据到服务器端, 而echo语句代表返回数据到客户端。
又由于Ajax属于客户端语言, 其接收的数据必须能返回到客户端, 否则是接收不到任何数据的。
ajax
avaScript 最早诞生于1995年,当时主要用来处理输入验证操作,随着时间的发展它成为了市面上浏览器必备的一项功能。如今JavaScript不仅仅局限于简单的数据校验,它已经具备与浏览器窗口及其内容几乎所有方面的交互能力,已经是一个功能全面的编程语言,能够处理复杂的交互和计算。
1995年Netscape 公司的布兰登.艾奇(Brendan Eich)着手开发一种名为 LiveScript的脚步语言。主要用于 Netscape Navigator 浏览器上,为了赶在浏览器发布前完成Livescript 的开发,Netscape 便和 Sun 公司合作,因此Netscape 为了搭上 Java的顺风车,把Livescrip改名JavaScript。
由于JavaScript 1.0版的巨大成功,成为了市场的领袖型公司,在当时的背景下,微软在其ie 3中加入了名为JScript的脚本语言,随着微软的加入,市场上出现多个不同版本的JavaScript,导致每个版本差异巨大,没有统一的标准,引起了许多问题。
于是在1997年,以JavaScript 1.1为基础版本提交给欧洲计算机制造商协会(ECMA)。随后,该协会推出了ECMAScript标准,各浏览器厂商都将此标准作为实现各自JavaScript的实现基础,也在不同程度上取得成功。
虽然通常JavaScript 和 ECMAScript被认为是相同的含义,但是JavaScript却比ECMA规定的内容要多得多。一个完整的JavaScript 由以下组成:
ECMAScript 其实与web浏览器没有依赖关系,它不依赖任何环境,web浏览器只是其实现的一种宿主环境。此外还有Node 和 Flash 也都是宿主环境,都实现了各自的ECMAScript 脚本。
ECMAScript 主要有以下核心内容:
2015年6月17日,ECMAScript 6发布正式版本,即ECMAScript 2015,简称ES6,ES6增添了许多必要的特性,例如:模块和类,以及一些实用特性,例如Maps、Sets、Promises、生成器(Generators)等。尽管ES6做了大量的更新,但是它依旧完全向后兼容以前的版本。
截止目前,ES6是各大浏览器支持较好的且稳定的一个版本,以后关于JavaScript的知识都会在ES6的语法基础上介绍。
文档对象模型(Document Object Model),是针对XML及其基础上扩展的HTML的应用程序编程接口(API)。DOM把整个网页映射成为一个树状的多层节点结构。页面中每个组成部分都是某种类型的节点,这些节点有包含不同的数据。如下面这个html页面:
<html>
<head>
<title>标题</title>
</head>
<body>
<p>段落文字</p>
</body>
</html>
通过DOM构建的节点树结构,我们可以很方便的控制页面的内容,比如删除、添加、修改任何节点的内容。
DOM主要内容
DOM 作为一种API,它也是有规范的,1998年DOM成为W3C的推荐标准,DOM从1.0到如今的3.0,其实现了更加丰富的接口,主要有如下这些模块:
处理DOM核心和DOM HTML接口外,另外其它语言也发布了针对自己的DOM标准。比如下面几种:
还有一些语言,比如 Mozilla 的XUL(XML 用户界面语言),但是只有上面几种是W3C推荐的标准。
如今,大部分浏览器已经全部支持DOM 1.0 、2.0版,3.0版也大部分都支持,所以我们可以放心的使用,尤其是最近IE浏览器的彻底退出舞台,浏览器兼容问题少了许多。
早期Netscape 浏览器和IE浏览器,都支持访问和操作浏览器窗口对象模型。开发者可以控制页面以外的部分,不同于其它,BOM作为JavaScript的实现却没有一个相关的标准。这个问题直到HTML5出现才得到解决,HTML5致力于把BOM纳入正式的规范中。
BOM从根本上讲,只处理浏览器窗口和框架,但人们都习惯把针对浏览器的JavaScript扩展归于BOM的范畴,下面是一些扩展:
由于BOM一直以来没有统一的规范,各个浏览器都有自己的实现,所以差距比较大,但是随着HTML5的发展,BOM朝着兼容性更高的方向发展。
JavaScript 是一种专门为网页设计的脚本语言,其主要由以下三个部分组成:
在当前主流浏览器中,对于ES6的大部分功能都得到了支持,随着技术的发展,JavaScript越来越完善,功能也更加强大。
参考资料:
《JavaScript 高级程序设计》第三版
MDN JavaScript 教程 —— https://developer.mozilla.org/zh-CN/docs/Web/JavaScript
*请认真填写需求信息,我们会在24小时内与您取得联系。