看完此文章,你将能够独立完成:html
- 在服务器上能够写一个简单的静态网页,并访问
- 能够为你的App写接口,提供Json格式的数据
- 服务器定时执行某项任务
上一篇经过访问公众号获取每日最新资讯的文章一出『这一次,他经过公众号访问最新的1024资讯信息』,真的是没想到,你们的热情一下那么高,致使个人服务器压力很大。让我真的是很意外,仍是要感谢你们的支持。上回答应过你们,要给你们说一下须要怎样作,才可以实现那样的功能。因此,这回我主要讲一下,如何用Tornado来搭建你本身的服务器。WeRoBot微信自动回复机器人下一期再说吧。前端
我敢打包票,85%的人看不完这篇文章。你们的自觉性就是这样。java
授人以鱼不如授人以渔,这就是我为何要写这些文章的原因。今天既然可以经过公众号来访问到小草,那么明天我就能够经过公众号上访问天天新闻的最新消息,或者我关注的人的微博更新,或者美剧是否又跟新了,或者视频网站是否又出新视频了,或者一些论坛是否发了最新的帖子,甚至天天早晨一块儿来,均可以经过本身的算法再结合昨天的股票数据,来推测今天大盘的涨跌,这些东西背后的原理其实都差很少的。因此,不要把本身的思路局限在一点,要扩散,要放开,这样才会有骚操做的出现。python
行了,废话不闲扯了,来开始说说咱们今天的主角:Tornado吧。web
Tornado就是龙卷风,哦不,这里说的Tornado是一种 Web 服务器软件的开源版本。Tornado 和如今的主流 Web 服务器框架(包括大多数 Python 的框架)有着明显的区别:它是非阻塞式服务器,并且速度至关快。算法
Tornado须要用Python编写,因此,这一系列下来,咱们都是用的Python来搞事情,就和我以前说的,Python这个语言,最适合搞事情了!mongodb
这里要说一点,Web框架有不少种,不一样语言有不一样的框架,并且特色都不同,就Ptyhon而言,用Python开发的Web框架也有好几种,Django,Flask,Tornado,这些框架,也是各有各的特色。因此,我想说的是,至于要用那种框架,请结合你自身的需求来选择。不要盲目的抓起一个随便用,这样未来会坑了本身。咱们这里,就是小型服务,自娱自乐用,因此,没有那么多顾虑,随便抓起来一个用就OK,这不,我抓的就Tornado。数据库
首先,服务器或者你本地的机器上面,应该是有Python的,推荐Python3,而后,你的机器应该是有pip的。json
咱们须要经过pip来安装Tornado后端
1# pip install tornado
复制代码
安装完成,若是想测试是否安装功,只须要进入Python,而后输入import tornado,若是没有报错,就说明安装成功。
接着,咱们来搞一下本地的配置。
本地,我推荐使用PyCharm来作IDE。这个IDE功能还算能够,若是你已经有本身习惯的IDE,能够略过此处。
PyCharm官网上有两个可下载的版本:
推荐下载第一个,Professional,这个版本功能很强大,并且支持不少Web框架的插件。
可是好多人会发现,这个是收费版本的啊,那怎么用?
别急,破解方法很是简单,第一次打开PyCharm的时候,选择License server激活,而后填入:http://im.js.cn:8888
或 http://idea.java.sx/
或http://xidea.online
,而后点Activate激活便可。
接着,咱们须要将本地的代码和服务端的代码要同步起来,作好映射,设置的步骤也很简单。这里,咱们假设远端的服务器地址是39.11.12.123
。
在Tools -> Deployment -> Configuration
里面:
点击左上角的 +
号:
出来的对话框里,名字随便写,可是下面的要选择SFTP
。
接着,下面这张图,第一个红框里面填写远程服务器的ip地址:39.11.12.123,第二个填写你服务器上的登陆帐户名称,通常是root,第三个就是密码。
接着第二页,Mapping里面,第二个红框里面,填写你本机的工程目录地址,第三个红框填写在服务器上的工程目录地址(提早建好)。
而后点击OK。接着,在Tools -> Deployment -> Automatic Upload
点击打钩,这样每次编写完一个文件,代码就能够自动同步到服务器上了。
每次若是须要同步的话,能够在Tools -> Deployment
菜单里面,选择Upload to XXXX
就行,或者在须要上传的文件图标点击右键,在Deployment
里面选择就能够。很方便。上传成功的样子大概就是这样:
好了,咱们接下来就要尝试着编写咱们的代码了。可是,对于第一次接触新框架的你,咱们仍是先看一下Tornad的“Hello World”怎么写吧。
1import tornado.ioloop
2import tornado.web
3
4class MainHandler(tornado.web.RequestHandler):
5 def get(self): # 3
6 self.write("Hello, world") # 4
7
8def make_app():
9 return tornado.web.Application([
10 (r"/", MainHandler), # 2
11 ])
12
13if __name__ == "__main__":
14 app = make_app() # 1
15 app.listen(8888)
16 tornado.ioloop.IOLoop.current().start()
复制代码
在这个里面,最关键的,有这么几个地方:
OK,上面简单的分析,就是Tornado处理一个网络请求的逻辑。捋顺这个逻辑以后,咱们接下来就开始简单的编写一下咱们本身的服务端代码吧。
明确一下咱们的两个目的:
好的,下面咱们就起来撸代码,不对,是撸起来代码。
遵循咱们上面所说的,定义url路径,而后写Handler。因此,我就先按照这个思路,把工程目录按照这个样子创建了一下:
而后,咱们在main.py
这个文件里面编写代码以下:
1class Application(tornado.web.Application):
2 def __init__(self):
3 handlers = [
4 (r"/web/", WebHandle),
5 (r"/json/", JsonHandle),
6 ]
7 # 定义tornado服务器的配置项,如static/templates目录位置,debug级别等
8 settings = dict(
9 debug=True,
10 static_path=os.path.join(os.path.dirname(__file__), "static"),
11 template_path=os.path.join(os.path.dirname(__file__), "templates")
12 )
13 tornado.web.Application.__init__(self, handlers, **settings)
14
15
16if __name__ == "__main__":
17 print("Tornado server is ready for service\r")
18 Application().listen(8000, xheaders=True)
19 tornado.ioloop.IOLoop.current().start()
复制代码
这里简单作一下解释:
咱们定义两个Handler,一个是返回网页版本的Handler,另外一个是返回Json版本的;咱们的Application的写法也和Hellow world例子
中写的不同,咱们这样写,能够自定义不少设置,好比路径,是否Debug模式之类的。
那么咱们接下来看看连个Handler怎么写的:
1# views.json
2class JsonHandle(tornado.web.RequestHandler):
3 def get(self, *args, **kwargs):
4 self.write("json view")
5
6# views.web
7class WebHandle(tornado.web.RequestHandler):
8 def get(self, *args, **kwargs):
9 self.write("web view")
复制代码
这里是两个及其简单的实现,咱们来看一下效果:
下面这个是访问错误的url出现的页面,由于咱们开了Debug模式,因此页面长这个样子:
404页面的问题咱们以后会说到。
到这里位置,咱们有一个地方不知道你们发现没有,十分的不灵活,就是上面url匹配的地方。这里指定了:http://xxxxxx/json/
只能用JsonHandler来处理,可是若是来了http://xxxxxx/json/XX
,他就会报错,页面未找到。处理这样的请求,让咱们的服务变得更增强大,更加健壮,咱们决定,新加一个url_router,在必定程度上,用它来控制咱们的url匹配。
1""" 2 url_router.py 3"""
4def include(module):
5 res = import_module(module)
6 urls = getattr(res, 'urls', res)
7 return urls
8
9
10def url_wrapper(urls):
11 wrapper_list = []
12 for url in urls:
13 path, handles = url
14 if isinstance(handles, (tuple, list)):
15 for handle in handles:
16 pattern, handle_class = handle
17 wrap = ('{0}{1}'.format(path, pattern), handle_class)
18 wrapper_list.append(wrap)
19 else:
20 wrapper_list.append((path, handles))
21 return wrapper_list
复制代码
有了router,咱们的main文件和handler文件都应该修改一下,在views.json和views.web目录下,分别创建json_urls.py
和web_urls.py
:
1""" 2 main.py 3"""
4class Application(tornado.web.Application):
5 def __init__(self):
6 # >>>> 不同的地方开始
7 handlers = url_wrapper([
8 (r"/json/", include('views.json.json_urls')),
9 (r"/web/", include('views.web.web_urls')),
10 ])
11 # 不同的地方结束 <<<<
12 # 定义tornado服务器的配置项,如static/templates目录位置,debug级别等
13
14""" 15 json_urls.py 16"""
17urls=[
18 (r'', JsonHandle)
19]
20
21""" 22 web_urls.py 23"""
24urls = [
25 (r"", WebHandle)
26]
复制代码
这样写,虽然看上去比较乱一些,可是至关灵活。可以使咱们的url变得丰富。好比,若是我想添加一个查看所有json文件的url,那么我只须要在json_urls
里面,添加一个(r'/all', GetAllHandler)
便可,而后在json_view.py
里面实现GetAllHandler
就能够了。这样作完,咱们的服务器就能够同时处理http://xxxxxx/json/
和http://xxxxxx/json/all
两个url了,并且是不一样的handler处理。
此时此刻,咱们大概的框架基本搭建完成。下面就来主要实现一下handler里面的功能吧。
由于咱们要实现的是从数据库里面读取了数据在显示到网页上,因此,这里咱们用到了PyMongo这个库。这个库是Python专门用来操做MongoDB的,炒鸡简单好用。
咱们先来完成Json部分。
咱们要在JsonHandler中,实现get()方法。这里,咱们首先从数据库中读取出来数据,而后,得将数据转换成dict()格式,由于PyMongo读取出来的数据,不可以直接转成Json,由于里面有个叫Object_id的东西,因此,这里咱们就手动转一下。而后,把数据用self.write(json.dumps({"data": {"block": return_data, "curTime": cur_time}}))
的形式返回回去就好。结构至关简单,大体代码以下:
1class JsonHandle(tornado.web.RequestHandler):
2 def get(self):
3 # 从数据库中读取数据
4 self.client = pymongo.MongoClient("mongodb://39.11.12.123/", 27017)
5 self.db = self.client["DailyProject"]
6 self.table = self.db["table"]
7 result = self.table.find()
8 # 获得当前时间
9 time = datetime.datetime.now()
10 cur_time = str(time.year) + "-" + str(time.month) + "-" + str(time.day)
11 # 筛选出合适的数据
12 temp_posts = []
13 posts = []
14 for item in result:
15 temp_posts.append(item)
16 temp_posts.sort(key=lambda k: (k['post_time'][-5:]), reverse=True)
17 for item in temp_posts:
18 if item['post_day_time'] == cur_time:
19 posts.append(item)
20 # 将数据转换成dict()类型,方便转换成Json
21 return_data = []
22 for item in posts:
23 temp_dic = {'postId': item['post_id'], 'postTitle': item['post_title'],
24 'postPartUrl': item['post_part_url']}
25 return_data.append(temp_dic)
26 # 返回Json格式的数据
27 self.write(json.dumps({"data": {"block": return_data, "curTime": cur_tim
复制代码
下面是效果:
这样,实现起来是否是超级酷。这里是实现了get方法,你也能够实现post方法来处理HTTP POST请求。具体的逻辑仍是要根据你具体的业务来编写。反正最后用json.dumps返回就能够了。
小技巧:若是你返回的json格式都差很少,能够抽离出来,写一个模板,之后返回结果直接将数据传给模板就好。不须要在每一个方法都写一遍json的格式,那样若是修改起来,会很费事儿。
Web返回结果,咱们这里就用到了html的东西。首先,咱们得在template
里面建一个index.html
文件。而后,在WebHandler中,最后返回结果写成:self.render("index.html", info=posts, today=cur_time)
这样就能够了。这里简单说一下,第一个参数,是你template里面对应的html文件。第二个参数和第三个参数,是你须要传给前端的数据。名字随便叫,可是要和html里面保持一致。
Handler的代码大体以下:
1class WebHandle(tornado.web.RequestHandler):
2 def get(self):
3 self.client = pymongo.MongoClient("mongodb://39.11.12.123/", 27017)
4 self.db = self.client["DailyProject"]
5 self.table = self.db["table"]
6 result = self.table.find()
7 time = datetime.datetime.now()
8 cur_time = str(time.year) + "-" + str(time.month) + "-" + str(time.day)
9 temp_posts = []
10 posts = []
11 for item in result:
12 temp_posts.append(item)
13 temp_posts.sort(key=lambda k: (k['post_time'][-5:]), reverse=True)
14 for item in temp_posts:
15 if item['post_day_time'] == cur_time:
16 posts.append(item)
17 self.render("index.html", info=posts, today=cur_time)
复制代码
因为名字要和前端一一对应,因此,前端的代码以下:
1<body>
2
3<h1>技术讨论 {{today}}</h1>
4
5{% for element in info %}
6<div class="post_block">
7
8 <p class="post_id">{{element['post_id']}}</p>
9 <a class="post_url" href="{{element['post_url']}}" data-url="{{element['post_url']}}" target="_blank">{{element['post_title']}}</a>
10 <p class="post_time">{{element['post_time']}}</p>
11
12</div>
13{% end %}
14
15</body>
复制代码
注意,后端传过来的today
对应的html里面的{{today}}
,info
则对应的for循环里面的info
。这种for循环,语法有点像DoT.js。别慌,这种前端的写法就那么几种,并非很难,看懂例子怎么写,就照猫画虎的往本身的html里面写就能够。
看到了吗,就是这么简单,最后咱们运行起来,效果以下:
处理404页面,只须要在main.py
文件的url中,加入一个(r".*", BaseHandle)
,而后在BaseHandler
里面,返回一个你已经写好的404.html
就行了。炒鸡简单。
最后,代码写好了,咱们须要把咱们的程序跑起来。
首先,将你的工程部署到你的服务器上,经过前文所讲的部署方法,成功传上去文件。
而后,登陆到你的服务器,进入工程指定的文件夹。
因为咱们的启动程序是在main.py
里面写的,因此,这里只须要输入指令:
1# sudo python main.py &
复制代码
就可让你的Tornado后台运行了!千万别忘了后面还有个&
。
若是要关闭你的运行程序,则须要输入:
1# ps -ef | grep main.py
复制代码
来查找你Tornado所在的进程,经过kill
指令关闭就可。
1# kill -9 <进程号>
复制代码
看到没有,这样就能够了。一个例子虽然很简单,可是这里能够扩展的地方有不少。不少同窗确定苦恼于不知道该怎么写服务端的代码,那么这篇文章所讲的东西能够很好的带你入门,而且入门还前进了一小步,由于并非简简单单的只给你写hello world。
前面还提到了能够用Tornado来定时执行任务,这个东西我就再也不这里说了,若是想更多交流的话,请关注『皮克啪的铲屎官』,点击下方的『进群交流』,来一块儿在群里讨论。
这些所讲的内容的代码,我也给你们共享出来,一样是关注『皮克啪的铲屎官』,回复『tornado』,便可得到下载地址。
【Python实战】手把手超详细教程教你Scrapy爬达盖尔社区,有彩蛋
【Python实战】用Scrapy编写“1024网站种子吞噬爬虫”,送福利
【Python实战】用代码来访问1024网站,送福利
【Python实战】用Scrapyd把Scrapy爬虫一步一步部署到腾讯云上
这么硬货的公众号,大家不关注一下啊?