内容简介:最近学了:point_right:在线demo点击这里:point_right:
最近学了 react ,一直想做一个项目,没有什么好的主意。因为自己也要租房住,就想到了 租房App 这个idea,参考豆瓣租房小程序,着手了这样一个简陋的前后端项目:smile:。
:point_right:在线demo点击这里
:point_right: 项目源码点击这里 ,你可以下载在本地运行,如果对你有帮助可以点一下 star 哈:grin:
// 你可以使用npm或yarn yarn install 运行你的数据库 // 必须!!! yarn server // 运行服务器, 连接的数据库在server目录下的config.js里配置 yarn start // 运行项目 复制代码
二、前端
- 项目技术栈
react+react-router+react-redux,用create-react-app脚手架生成。UI方面采用Ant Design Mobile:point_right:官方地址。 -
css方案是css-in-js,采用style-jsx,:point_right: github地址 ,可参考掘金上的一篇文章:point_right:点击这里。 - 由于是移动端,避免不了
适配问题,采用vm/vh适配,具体同样可以参考掘金的:point_right:这篇文章。 - 在结合 2、3 两点时,由于要添加配置项,但我不想在项目中
run eject弹出,于是用了react-app-rewired改写配置,这样就不用弹出命令了。:point_right: github地址 - 权限路由。思路是根据遍历路由配置表,需要权限的走权限路由,不需要的走原来的路由。具体可看项目中的 router 部分。
- 图标采用
iconfont SVG处理
具体用法查看官方地址。
遇到的问题:
- (未解决)在dev开发环境下修改scss中的css,不会实时编译更新
- (未解决)IOS下通过
focus事件不能唤起键盘,安卓下可以 。为了有个较好的用户体验,我在登录,搜索页面打开时,让输入框自动focus唤起键盘,经IOS真机实践,只能触发focus事件,但是不会唤起键盘,安卓正常。查阅资料后是IOS做的限制,(IOS还有和音频、视频不能自动播放的限制)。需要用户主动点击输入框后,才可以唤起键盘。下一次重新打开就能自动唤起键盘了,很坑的一点:unamused:! 目前无解 - (解决) 从首页列表点击详情时候,返回到首页,会 重新请求加载 ,并且 滚动位置丢失 ,用户体验十分不好。这里为了学习
redux我用redux(也可用react的新context api)解决,因此在路由方面也用了react-redux-router,但已不维护,改为connect-react-routergithub点这里 。思路是首次获取房源列表,然后存入redux中,下次打开的时候,从redux中获取。 - (解决)
热加载后不能保存redux中的状态。解决方法:在store中,添加以下代码, 详细看这里
if (module.hot) {
// Reload reducers
module.hot.accept('./reducers', () => {
store.replaceReducer(connectRouter(history)(rootReducer));
});
}
复制代码
- (解决??) 用了
react-loadble加载项目中的搜索页面,会有搜索input的placeholder显示不全的问题,初次打开会有问题,第二次打开没有问题,如下图。 在dev环境下不能重现,生产环境下会有问题。该组件为Ant Design Mobile的searchBar。 上图我们可以看到是宽度的问题,正常应该为110px,而错误的时候则才80px。 暂时解决方法:移除该路由懒加载,直接加载:smirk:
项目优化:
- 路由懒加载,方案: react-loadable ,添加
loading提示 - 图片懒加载,方案: lazyload
- 封装成一个组件:point_right: 具体代码
- 这里需要说明在你的网站上加载豆瓣的图片都是
403的,因此我们需要用到下面这个网站来加载图片点击这里,使用方法https://images.weserv.nl/?url=+图片原来的地址, 详细参考上一步代码中的链接
-
ajax视情况添加loading提示,添加CSS3动画,使交互更加友好。
三、后端
- 采用
koa2+koa-router+mongodb+jsonWebToken。最主要的是需要注意 异步和异常处理 的问题。 - 数据库方面用了
Mongoose来操作。Mongoose是在node.js异步环境下对mongodb进行便捷操作的对象模型工具。更多详细说明请看官方文档::point_right:点击这里
3.1 爬取豆瓣小组数据
- 用到的
http库是axios。 - 定时任务库,
node-schedule。github::point_right: 点击这里 - 爬虫库
cheerio,它的用法十分简单。
const cheerio = require('cheerio')
const $ = cheerio.load('<h2 class="title">Hello world</h2>')
复制代码
这里我们就可以通过 $(selector) ,像 jquery 一样的方式取到页面的元素。官方文档::point_right:点击这里
整个爬取的流程:
- 初始化的时候判断是否大于最大存储的数据长度(此项目中设置了数据库最多储存
5000条数据),如果 超过 ,则执行删除,反之跳过。 - 开启一个定时任务,每天的
0.00am开始爬取=>爬取列表页面=>存入数据库=>如果 失败 ,不会爬取该条tid - 的详情页, 反之 继续爬取详情页。
- 爬虫提取信息用到了一些正则表达式,提取房租、联系方式、房型、所在地区等等。具体代码::point_right: 点击这里 。其中参考了:point_right:这篇文章中的一些正则表达式。
注意:豆瓣会限制一个时段内Ip的访问次数,因此需要我们做一些调整。
- 列表页面每一页、 详情页每一条数据的爬取的间隔时间保证是不同的。 (定时器+随机数时间) (貌似没什么卵用?)
// sleep
function sleep(time = 0) {
return new Promise(resolve => {
setTimeout(resolve, time);
});
}
// 更新数据库函数
async updateTopic(tid, resolve, reject) {
// 睡眠
await sleep(Math.ceil(Math.random() * 50 * 1000) + 5000);
// 开始更新
await this.fetchDetail(tid).then(houseInfo => {...});
}
复制代码
- 改变请求头的
user-agent。项目中是有个user-agent列表:point_right: 查看代码 ,每次请求都带上随机中的一个。
3.2 存入数据库
这里我是一次性插入多条数据,用到的 api 如下
db.Houses.insertMany([your array data]) 复制代码
3.3 写接口(路由)
需要注意的是部分路由(需要用户登录后才可以访问的接口) header 中需要传递 token 才能访问,因此添加 路由中间件校验 , 通过校验 后才允许访问。 详细代码查看这里 。关键代码如下:point_down:
const jwt = require('jsonwebtoken');
const token = ctx.header['x-token'];
if(token){
解析token得到用户信息
进入下一个中间件
}else {
返回错误需要传递token
}
复制代码
四、数据库mogodb相关
4.1 修改数据库相关结构
开始设计数据库的时候,设置价格字段 prices 是数组,后觉得字符串就可以了。于是在原数据库的基础上修改 数据格式 及 字段名 prices => price
- 批量更新某个字段
db.getCollection('houses').find().forEach(function(item){
db.getCollection('houses').update({_id:item._id},{$set:{prices: ''+item.prices}})
})
复制代码
- 更改字段名
// 如将字段"prices"改为"price"
db.getCollection('houses').update({},{$rename:{'prices':'price'}}, false, true)
复制代码
4.2 附上一些api.
- 数据库复制。如复制 douban-house 数据库到 douban-test
// db.copyDatabase(<from_dbname>, <to_dbname>, <from_hostname>)
db.copyDatabase('douban-house', 'douban-test')
复制代码
- 查找数据库中 数组长度大/小于n 的数据
// 大于 exists=1 小于exists=0
db.getCollection('houses').find({'imgs.n':{'$exists':1}})
复制代码
- 查找数据库中 某个字段不为null 的数据
// $ne=> not equal
db.getCollection('houses').find({'contact':{$ne:null}})
复制代码
- 查找数据库中 多条某个字段 的数据
db.getCollection('houses').find({'tid':{$in:['这里是数组','例如id1','2']}})
复制代码
另外:插入字段数字 Number Int 类型的数据会存储为 Double 类型,会带有小数点,例如存的是 10 ,存进数据库之后会变成 10.0 ,可以用 NumberInt 或者 NumberLong 来存储
db.houses.insert({"tid": NumberInt(666)})
复制代码
4.3 遇到的问题
爬虫爬取贴子的时候,会爬到相同的贴子,而我们是不需要这些重复的。这里的问题是在插入重复值的时候, 出现错误之后不会继续插入剩下的数据 ,这是很坑的一点。 下面是解决方法:
- 先设置
mongodb的唯一索引值,在设置的时候也遇到不少的坑,查了很多资料,总结相关的apiconst housesSchema = new mongoose.Schema({ tid: String, //我这里设置的唯一索引是每条贴子的id号 ...省略 }) housesSchema.index({ tid: 1 }, { unique: true }); 复制代码 - 这里设置好之后,当插入重复的tid时,数据库会返回错误,不插入该条数据。特别需要说的 大坑 是插入的api无论是
insert还是insertMany, 他们的api如下
db.collection.insert(
<document or array of documents>,
{
writeConcern: <document>,
ordered: <boolean>
}
)
复制代码
这里需要注意的是`ordered`这个参数, 这是一个可选参数,官方解释如下 复制代码
Optional. A boolean specifying whether the mongod instance should perform an ordered or unordered insert. Defaults to true.
大意就是指定mongod实例是否应执行有序插入。默认为```true```。 **重点是:**当有序插入的时候,如果出现了错误,程序会停下当前的插入,不执行插入剩余的数据。只有当无序插入,也就是设置了```ordered: false```,当出现错误之后,才会把剩下的继续插入。官方说明如下: > Excluding Write Concern errors, ordered operations stop after an error, while unordered operations continue to process any remaining write operations in the queue. 官方文档链接::point_right:[点击这里](http://docs.mongodb.com/manual/reference/method/db.collection.insertMany) 复制代码
五、部署相关(跨域处理)
- 开发阶段 可在项目中的
package.json中添加proxy字段, 这里假设http://localhost:3003就是我们的后台服务器,http://localhost:3000是react开发时候的服务器 如:在项目中访问http://localhost:3000/api/house/125048127就会代理到http://localhost:3003/api/house/125048127, 就没有跨域问题了
"proxy": {
"/api": {
"target": "http://localhost:3003"
}
}
复制代码
- 线上环境 nginx 配置代理 :point_right:参考这里
location /api/ {
proxy_pass http://localhost:3003;
}
复制代码
六、git相关
有时候提交了错误的代码又想回退版本,就需要回退远程 git 仓库的代码,再重新提交。 :point_right:更多用法参考这里
git reflog // 查看提交列表, 如我需要撤回到第二条提交记录,也就是红线下的那条 git reset --soft 3a2a12d // 这里的参数--soft表示保留本地修改记录, --hard 代表保存本地的记录,如果是--hard 则会清空本地修改记录,也就是你修改的都没有了!!切记!!! git push -f //强制推送到远程分支 复制代码
以上所述就是小编给大家介绍的《做一个跑通前后端的`豆瓣租房`移动端webApp》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- 一款租房 APP,基于 Node.js 爬虫
- 爬取两万多租房数据,告诉你广州房租现状
- 到今年6月 北京市所有公租房都将安装人脸识别系统
- 北京五环实录:合租房里互不相识,凌晨四点互联网大厂上班
- 租房有深坑?手把手教你如何用R速读评论+科学选房
- 编写豆瓣相册下载器(python爬虫)
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Computing Patterns in Strings
Bill Smyth / Addison Wesley / 2003 / $ 75.00
The computation of patterns in strings is a fundamental requirement in many areas of science and information processing. The operation of a text editor, the lexical analysis of a computer program, the......一起来看看 《Computing Patterns in Strings》 这本书的介绍吧!