16.tornado操作之聊天室和爬取图片功能整合
Posted 孤寒者
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了16.tornado操作之聊天室和爬取图片功能整合相关的知识,希望对你有一定的参考价值。
本文实现一个新功能,也是在聊天室和爬取图片功能的基础上,实现:在聊天室发送图片链接实现自动下载(即之前的上传图片功能)。
聊天室和爬取图片功能都已实现,所以上述所讲新功能的实现只需要对这俩功能整合一下即可~
- 也就是使用 AsyncHTTPClient 和 IOLoop.current().spawn_callback调用 /async接口即可。
前面实现聊天室功能时候有两个版本代码(《14.tornado操作之应用Websocket协议实现聊天室功能》,对应这个文章的第3和第4两个部分),所以本文的新功能也对应两个版本代码:
目录:
每篇前言:
🏆🏆作者介绍:【孤寒者】—CSDN全栈领域优质创作者、HDZ核心组成员、华为云享专家Python全栈领域博主、CSDN原力计划作者
- 🔥🔥本文已收录于tornado框架从入门到实战专栏:《tornado框架从入门到实战》
- 🔥🔥热门专栏推荐:《Django框架从入门到实战》、《爬虫从入门到精通系列教程》、《爬虫高级》、《前端系列教程》、《tornado一条龙+一个完整版项目》。
- 📝📝本专栏面向广大程序猿,为的是大家都做到Python从入门到精通,同时穿插有很多很多习题,巩固学习。
- 🎉🎉订阅专栏后可私聊进一千多人Python全栈交流群(手把手教学,问题解答); 进群可领取Python全栈教程视频 + 多得数不过来的计算机书籍:基础、Web、爬虫、数据分析、可视化、机器学习、深度学习、人工智能、算法、面试题等。
- 🚀🚀加入我一起学习进步,一个人可以走的很快,一群人才能走的更远!
1.对应聊天室第3部分代码实现
- 其实我在聊天室那篇文章中,我使用的代码就是第4部分的,因为极简,可拓展性高,而且代码十分通俗易懂!
- 所以后续(包括本文新增的这个功能)我重点对我所用的代码版本进行适当的更新迭代~
(1)修改chat.py文件:
from pycket.session import SessionMixin
import tornado.web
from tornado.ioloop import IOLoop
from tornado.httpclient import AsyncHTTPClient
class RoomHandler(AuthBaseHandler):
"""
聊天室的页面
"""
@tornado.web.authenticated
def get(self, *args, **kwargs):
self.render('room.html',messages=ChatWsHandler.history[:10:])
class ChatWsHandler(tornado.websocket.WebSocketHandler, SessionMixin):
"""
处理和响应 websocket 连接
"""
waiters = set() # 等待接收信息的用户
history = [] # 存放历史信息
def get_current_user(self):
return self.session.get('tudo_user',None)
def open(self,*args,**kwargs):
# 新的websocket 连接自动调用的操作
print('new connection:'.format(self))
ChatWsHandler.waiters.add(self)
def on_close(self):
# 关闭一个新的连接
print('close ws connection:'.format(self))
ChatWsHandler.waiters.remove(self)
def on_message(self,message):
# 将接收的数据转换一下
print('got message:'.format(message))
parsed = tornado.escape.json_decode(message)
# 接收数据
chat =
'id': str(uuid.uuid4()),
'body': parsed['body']
# 判断用户是否有输入内容和用户是否输入网址以http开头
if chat['body'] and chat['body'].startswith('http://'):
# 模拟浏览器发送请求获取数据
client = AsyncHTTPClient()
# 获取数据
save_api_url = 'http://192.168.182.141:8002/s?save_url=&user=&from=room'.format(
chat['body'],
self.current_user
)
print(save_api_url)
IOLoop.current().spawn_callback(client.fetch,save_api_url)
# client.fetch(save_api_url)
# 告诉用户你发送的url正在处理
msg = 'user , url is processing.'.format(self.current_user,chat['body'])
# 将信息告诉用户,不做全部显示
chat['body'] = msg
# 显示内容到页面
message_html =
'html': tornado.escape.to_basestring(
self.render_string('message.html', chat=chat)
),
'id': chat['id']
self.write_message(message_html)
else:
# 显示聊天内容的页面和连接
message_html =
'html': tornado.escape.to_basestring(
self.render_string('message.html',chat=chat)
),
'id': chat['id']
ChatWsHandler.history.append(message_html)
ChatWsHandler.send_updates(message_html)
print('got message:'.format(message))
# 给每个等待的用户发送新的信息
@classmethod
def send_updates(cls, message_html):
for w in ChatWsHandler.waiters:
w.write_message(message_html)
(2)修改service.py文件:
from .chat import ChatWsHandler
import uuid
class AsyncSaveHandler(AuthBaseHandler):
"""
使用异步
"""
def prepare(self):
print(self.get_argument('save_url','empty'))
@tornado.gen.coroutine
def get(self,*args,**kwargs):
save_url = self.get_argument('save_url',None)
print(save_url)
# 获取用户名和接口
username = self.get_argument('user',None)
is_from_room = self.get_argument('from',None) =='room'
print(username)
print(is_from_room)
if username and is_from_room:
resp = yield self.get_rep(save_url)
ims = UploadImage(self.settings['static_path'],'x.jpg')
ims.save_upload(resp.body)
ims.make_thumb()
# post = add_post(self.current_user,ims.image_url,ims.thumb_url)
post = add_post(username,ims.image_url,ims.thumb_url)
# self.redirect('/post/'.format(post.id))
# 告诉用户你的图片保存完成
import uuid
chat =
'id': str(uuid.uuid4()),
'body': 'new picture from : http://192.168.182.141:8002/post/'.format(username,post.id),
message_html =
'html': tornado.escape.to_basestring(
self.render_string('message.html', chat=chat)
),
'id': chat['id']
#
ChatWsHandler.send_updates(message_html)
# self.write(post.id)
else:
# 如果不符合
print('wrong call')
self.write('wrong call')
#使用延迟的方式
@tornado.gen .coroutine
def get_rep(self,url):
yield tornado.gen.sleep(5)
client = AsyncHTTPClient()
resp = yield client.fetch(url)
return resp
2. 对应聊天室第4部分代码实现
(1)修改chat.py文件:
import datetime
import tornado.websocket
from tornado.httpclient import AsyncHTTPClient
from tornado.ioloop import IOLoop
from .main import AuthBaseHandler
# 聊天室页面
class RoomHandler(AuthBaseHandler):
def get(self):
uname = self.current_user
self.render('room.html', uname=uname)
# 聊天中转站:websocket
class ChatWsHandler(tornado.websocket.WebSocketHandler, AuthBaseHandler):
# 在线用户
online_users = []
# 存放历史聊天信息
history = []
# 连接:当有新用户连接我时,会自动调用
def open(self, *args, **kwargs):
# print('有新用户加入聊天室...')
self.online_users.append(self)
# 给新用户展示所有历史记录信息
for i in ChatWsHandler.history:
self.write_message(i)
# 添加历史聊天信息之用户登录信息
message = u"[%s]-[%s]-进入聊天室" % (self.current_user, datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"))
ChatWsHandler.history.append(message)
# 向所有在线用户发送消息——告诉有新人登录
for u in self.online_users:
u.write_message(message)
# 接收信息:接收前端浏览器发过来的信息
def on_message(self, message):
# print("接收到前端用户发过来的信息:", message)
# 不能发送空信息
if message:
# 判断用户是否输入网址以http或https开头
if message.startswith('https://') or message.startswith('http://'):
# 模拟浏览器发送请求获取数据
client = AsyncHTTPClient()
# 结合异步操作获取数据
save_api_url = 'http://127.0.0.1:8000/async?save_url=&user=&from=room'.format(
message,
self.current_user
)
IOLoop.current().spawn_callback(client.fetch, save_api_url, request_timeout=30)
message= u"[%s]于[%s]发送的url:<a href='%s' target='_blank'>%s</a>正在下载中..." % (
self.current_user,
datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
message,
message
)
ChatWsHandler.send_updates(message)
else:
message = u"[%s]-[%s]-说:%s" % (self.current_user, datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"), message)
# 添加历史聊天信息之用户新发送的聊天信息
ChatWsHandler.history.append(message)
# 给每个等待的用户发送新的历史聊天记录信息
ChatWsHandler.send_updates(message)
@classmethod
def send_updates(cls, message):
"""给每个登录的用户发送新信息"""
for w in ChatWsHandler.online_users:
w.write_message(message)
# 关闭:有用户退出聊天室时会自动调用
def on_close(self):
# print("有用户已经退出聊天室!!!")
self.online_users.remove(self)
message = u"[%s]-[%s]-离开聊天室" % (self.current_user, datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"))
# 向所有在线用户发送消息——告诉有人退出
for u in self.online_users:
u.write_message(message)
# 添加历史聊天信息之用户退出信息
ChatWsHandler.history.append(message)
(2)修改service.py文件:
import tornado.gen
import tornado.web
from tornado.httpclient import AsyncHTTPClient
class AsyncSaveHandler(AuthBaseHandler):
"""
异步上传指定url的图片功能
"""
@tornado.gen.coroutine
def get(self,*args,**kwargs):
save_url = self.get_argument('save_url', None)
username = self.get_argument('user', None)
is_from_room = self.get_argument('from', None) == 'room'
# 确保用户登录且源于room页面
if username != 'None' and is_from_room:
try:
resp = yield self.get_rep(save_url)
upload_im = UploadImage(self.settings['static_path'], '.jpg'.format(uuid4().hex))
# 1.用户上传图片的保存
upload_im.save_upload(resp.body)
# 2.生成用户上传图片对应的缩略图并保存
upload_im.make_thumb()
# 3.用户上传图片数据的入库
post = add_post(username, upload_im.image_url, upload_im.thumb_url)
message = "新图片保存成功-> <a href='http://43.142.78.214:8000/post/' target='_blank'>http://43.142.78.214:8000/post/</a>".format(post.id, post.id)
ChatWsHandler.send_updates(message)
except:
ChatWsHandler.send_updates('您刚发送的url对应图片因为未知力量保存失败!')
else:
# 如果不符合
ChatWsHandler.send_updates('请登录之后再进行操作!')
# 使用延迟执行
@tornado.gen.coroutine
def get_rep(self,url):
# yield tornado.gen.sleep(5)
client = AsyncHTTPClient()
resp = yield client.fetch(url, request_timeout=30)
return resp
实现效果:
以上是关于16.tornado操作之聊天室和爬取图片功能整合的主要内容,如果未能解决你的问题,请参考以下文章
用python爬取豆瓣电影信息,输入类别和爬取页数,想怎么爬就怎么爬,哎就是玩!