跳过正文

利用socketIO实现爬虫实时新闻推送系统

·189 字·1 分钟
Remy
作者
Remy
Bug的设计师,故障的制造机,P0的背锅侠。代码里的隐秘问题总能被我创造性地解锁。写代码如同解谜,有时谜底是惊喜,有时是惊吓。

何为socketIO,何为Websocket:
#

Websocket是什么
#

WebSocket是为解决客户端与服务端实时通信而产生的技术。其本质是先通过HTTP/HTTPS协议进行握手后创建一个用于交换数据的TCP连接, 此后服务端与客户端通过此TCP连接进行实时通信。

SockectIO又是什么?
#

简单说是对websocket的协议的封装,客户端SocketIO能够更简单的方法实现这一协议,并且如果浏览器使用的老式的浏览器,也能通过使用长链 接的方式实现相同的效果.服务端对各大语言支持也非常不错.而且极容易使用

为何使用Websocket:
#

首先看需求:
#

  1. 我们的爬虫需要到目标网站每分钟爬取实时内容.
  2. 内容需要及时发送我们的网站上

那么收先解决的问题就是爬虫如何通知服务端,服务端如何推送至浏览器的问题.

ajax轮询方式:
#

我们web一直都是请求->响应的模型,怎么才能内容推送至客户端,ajax轮询就是通过脚本,每隔一段时间向服务端发送请求,于是我们就看到了 如下的情况:

客户端: hi,服务端有新数据吗?

服务端:没有哦,

一分钟…

客户端:hi,有新数据更新吗?

服务端:没有哦

又一分钟过去了……

客户端: hi,有新数据吗?

服务端:你烦不烦啊,没有啊,

一分钟后….

客户端:hi,有数据吗?

服务端:有了有了,给你了,好烦啊

看到了吧,首先,每次http的请求都相当耗时耗流量,而且这种模型极为损耗性能,那么,什么办法才能解决呢,于是HTML5的新协议,websocket应对这种需求 应运而生…

Websocket的方式:
#

如果改用了Websocket的方式我们就变成了这样的情景

客户端:hi,在吗?

服务端:恩,在,你在吗?

客户端,恩,我在,有信息记得通知我哦,我就呆这里不走了,

服务端:好,我这边有信息了,给你,你有什么告诉我的吗?

客户端: 没啥告诉你的….

……..

显然,这样的方式,应对这种需求就变得更加高效,那么我们该如何时使用呢?

使用:
#

这里用python来实现,首先需要使用以下的包:

  • flask-SocketIO
  • SocketIO_client
  • js的SocketIO_client

然后我们看看我们的实现原理图:

好了,直接上代码:

爬虫端:
#

class NewsObserver(Observer):
    def update(self):
        logger_kxt.info(u"开始爬取")
        news = NewsSpiderNews().spiderfirstNews()
        socketIO = SocketIO('localhost', 5000) #定义websocket的服务器
        for new in news:
            news_obj = News.objects(news_id=new.news_id).first()
            if news_obj == None:
                new.save()
                logger_kxt.info(u'实时新闻:%s:%s更新成功'%(new.time,new.content))
                msg_namespace = socketIO.define(BaseNamespace) #socketIO命名空间
                msg_namespace.send(str(new.news_id)) # 发送信息
            else:
                logger_kxt.info(u'实时新闻:暂无更新')
        socketIO.disconnect() # 本次信息发送完成后断开链接

服务端:
#

from app import socketio
from common.logger import logger_zwoil

# 接受爬虫推过来的数据推送至客户端!
@socketio.on('message')
def handle_message(message):
    logger_zwoil.info(u'received message: ' + message)
    news = News.objects(news_id=int(message().first()
    socketio.emit('my response', data, broadcast=True)#将信息广播所有客户端
    logger_zwoil.info(u'push successfully')

浏览器客户端:
#

  1. 首先,我们要将SockeIo依赖添加到html内:

     <script type="text/javascript" src="/static/js/jquery.min.js" charset="utf-8"></script>
     <script type="text/javascript" src="/static/js/socket.io-1.4.5.js" charset="UTF-8"></script>
    
  2. 然后使用:

         var news = io("http://127.0.0.1:5000/");
     news.on("news",function (data) {
         console.log(data);
         $(".news").prepend("<li>"+data+"</li>")
     });
    
  3. 完整的html代码:

     <!DOCTYPE html>
     <html lang="en">
     <head>
         <meta charset="UTF-8">
         <title>新闻列表</title>
         <script type="text/javascript" src="/static/js/jquery.min.js" charset="utf-8"></script>
         <script type="text/javascript" src="/static/js/socket.io-1.4.5.js" charset="UTF-8"></script>
    
     </head>
     <body>
     <script>
         var news = io("http://127.0.0.1:5000/");
         news.on("news",function (data) {
             console.log(data);
             $(".news").prepend("<li>"+data+"</li>")
         });
     </script>
     <ul class="news">
         <li>这些都是原来的新闻</li>
     </ul>
     </body>
     </html>
    

结语:
#

使用SocketIO能干许多事情,可以利用这一协议,推流,推信息,聊天,甚至网络游戏也可以这样实现,更多使用,请看官方文档,介绍的都很详细: