获取书房列表
和身份有关的数据都会通过token的校验获取openid
来进行
else if(action=="listmy"){ dbRes = await db.collection('bookshelfs').where({ owner:dbCmd.eq(payload.openid) }) .orderBy("_id","desc") .limit(10) .get() }
寻找距离我最近的书房
else if(action=="listbygeo"){ dbRes = await db.collection('bookshelfs').field({owner:false}).where({ geopoint:dbCmd.geoNear({ geometry: new db.Geo.Point(event.longitude, event.latitude), maxDistance: 3000,//单位米 minDistance: 0 }) }) .limit(100)//做个数量限制 .get() }
修改书房
else if(action=="update"){ const res = await msgSecCheck(payload.openid,event.name); if(res.result.suggest!="pass"){ return {err:1,msg:"内容不安全"}; } dbRes = await db.collection("bookshelfs").where({ "_id":dbCmd.eq(event._id), "owner":dbCmd.eq(payload.openid) }).limit(1).update({ name:event.name, address:event.address, geopoint:new db.Geo.Point(event.longitude, event.latitude) }) return dbRes; }
删除书房
else if(action=="delete"){ dbRes = await db.collection("bookshelfs").where({ "_id":dbCmd.eq(event._id), "owner":dbCmd.eq(payload.openid) }).remove(); }
图书数据库
通过ISBN爬取豆瓣图书信息
首先通过scanCode
api来扫描图书背后的条码,获取到条码信息后通过云函数向某瓣爬取图书标题和封面
let { isbn } = event; let res = await uniCloud.httpclient.request("https://search.douban.com/book/subject_search?search_text="+isbn+"&cat=1001"); let reg = /window\.__DATA__ = "(.*)"/; if(reg.test(res.data)){ let bookdata=RegExp.$1;//这是数据是被加密的,需要解密 }
爬取到的信息需要解密,本文就不讲述解密过程了,小伙伴们可以自行看源码。
这个爬虫违法吗?我认为不违法,因为封面,标题信息属于公开信息,不从某瓣爬,我们也可以从别的地方获取,比如图书电商,比如付费API等。另外我们并没有收集某瓣对于图书的评分,评论等这些某瓣独有的数据。
不过有其他意见的小伙伴可以在评论区帮我普普法
建立自己的ISBN库
- 封面图上传至云存储
let coverImage = await uniCloud.httpclient.request(data.cover_url); let uploadResult = await uniCloud.uploadFile({ cloudPath:isbn+".jpg", fileContent:coverImage.data })
- 自己的ISBN数据库
let resData = { isbn:isbn, title:data.title,//图书标题 cover_url:uploadResult.fileID,//封面在云存储的url地址 abstract:data.abstract//图书附加信息 } dbResult = await db.collection("isbnlib").add(resData);
那么有了自己的ISBN数据库,下次再有用户扫描相同的图书时,信息就不用再去爬取了,直接从自己的ISBN数据库返回,这也是一种利用众包
的机制来建立数据库的方法
let dbResult = await db.collection("isbnlib").limit(1).where({ isbn:isbn }).get(); //数据库里已有相同ISBN的话,则直接返回数据库里的信息 if(dbResult.affectedDocs>0){ return dbResult.data[0]; }
书架图书数据库
放到书架上的图书,我们新建一个books的表来管理,并绑定书架id
和isbn
- 从ISBN库获取图书信息
const bookInfo = await db.collection("isbnlib").doc(event.isbnid).get();
- 建立图书数据
绑定书架id,isbnid,openid等,确定图书是谁的,在哪个书架里。
dbRes = await db.collection("books").add({ owner:payload.openid, shelfid:event.shelfid, title:bookInfo.data[0].title, cover_url:bookInfo.data[0].cover_url, isbn:bookInfo.data[0].isbn, isbnid:event.isbnid, createtime:now, updatetime:now, });
- 书架里图书总数字段更新
await db.collection("bookshelfs").where({ owner:payload.openid, _id:event.shelfid, }).update({ totalbook:dbCmd.inc(1)//inc就是在当前字段的数值基础上增加 }) return dbRes;
- 图书的搜索
dbRes = await db.collection('isbnlib') .where({ title=new RegExp(event.keyword, 'i') }) .orderBy("_id","desc") .orderBy("updatetime","desc") .limit(12) .get();
生成书架海报
利用canvas
生成海报,canvas里的绘制细节大家看项目源码吧。这里我主要使用小程序码接口来获取带有参数的小程序码。
生成小程序码的API一共有三种,其中接口A和接口C是数量有限的,最多只能生成10w个。万一这个小程序用户量大了,书房书架数量超过10w个,那就不能用接口A了。所以我们要使用接口B
,数量无限。
- 云函数调用wxacode接口
const access_token = await getAccessToken(); const res = await uniCloud.httpclient.request("https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token="+access_token,{ method:"POST", headers:{ "Content-Type":"application/json" }, data:{ scene:"微信扫码后小程序里可以获取到的信息", page:"扫码后进入的小程序页面" } });
但这个接口B的局限是scene
字段最长32个字符,参数名只能叫scene。并且该接口只能用于已发布的小程序。
结语
这是我2017年共享图书项目的核心技术部分,用uniCloud重新实现,本文像记流水账一般把核心过程给分享了出来,阅读体验可能不佳,不过分享不易,还请大家多多点赞支持。