3.aiohttp中websocket的使用

目录

1.什么是websocket

2.如何在aiohttp中使用websocket

3.如何在vue中使用websocket


1.什么是websocket

对于传统的web开发而言,是前台发送请求,后端接口返回对应的数据。但是在爬虫网页项目中当用户在页面上发送爬取请求之后,这个时候如果是传统的ajax请求,则前台就会阻塞,并且我们需要后台实时的通知用户现在爬虫的爬取进度。为了完成这一系列的交互功能,我们就需要使用websocket。websocket本质上就是一种协议,这种协议可以允许服务端主动给客户端客户端推送数据,在与vue相结合之后可以实现实时的数据刷新与展示效果。

2.如何在aiohttp中使用websocket

aiohttp中自带了websocket,并且是异步实现。这就意味着可以实时向客户端推送最新的数据。在flask中如何想实现这样功能的websocket则需要使用celery任务队列来完成。对于aiohttp来说使用websocket只需要以下的代码

async def websocket_handler(request):

    ws = web.WebSocketResponse()  
    await ws.prepare(request)  # 等待websocket连接

    async for msg in ws:
        if msg.type == aiohttp.WSMsgType.TEXT:
            if msg.data == 'close':
                await ws.close()
            else:
                await ws.send_str(msg.data + '/answer')
        elif msg.type == aiohttp.WSMsgType.ERROR:
            print('ws connection closed with exception %s' %
                  ws.exception())

    print('websocket connection closed')

    return ws

也可以使用ws.send_json来直接向前台发送json格式的数据,需要注意的是如果含有中文的话需要将ensure_ascii设置为False

3.如何在vue中使用websocket

在vue中使用websocket可以使用原始的websocket,也可以使用websocketio,这里我后台使用的是aiohttp的websocket,所以在vue中直接使用的是websocket。为了便于websocket的统一管理,我将websocket放到了vuex中进行全局管理,具体的大致芦逻辑如下,以登陆电影界面为例:

(1) 在用户登陆之后默认连接所有的websocket,用户退出之后默认断开所有的websocket(因为此时可能还有其他的爬虫任务正在后台运行,需要后台实时向前台推送数据)

(2)在进入需要使用websocket的界面之前检查websocket的状态,如果没有连接则连接之

(3)在离开需要使用websocket的界面之后,检查对应的websocket的任务状态,如果没有任务在运行则断开

(4)综上,将websocket放在vuex中进行管理,具体代码如下

store中的代码

import restFulUrl from "@/utils/config"

const state = {
  // movie websocket的连接状态管理
  movieSocket: {
    socket: '',  // websocket连接
    taskState:'' // 当前websocket的任务状态
  },

}

const mutations = {
  CONNECT_Movie: (state) =>{
    state.movieSocket.socket = new WebSocket(restFulUrl().replace("http", "ws") + "/search_movie") // 连接websocket
},
  DisConnect_Movie: (state) =>{
    state.movieSocket.socket.send(JSON.stringify({'state': 'close'}))
    state.movieSocket.socket = ''  // 断开连接
    state.movieSocket.taskState = ''  // 还原任务状态
  },
  Set_Movie_Task_State: (state, taskState)=>{
    state.movieSocket.taskState = taskState  // 设置任务状态
}
}

const actions = {
  connectMovie({commit}){
    commit('CONNECT_Movie')
  },
  disconnectMovie({commit}){
    commit('DisConnect_Movie')
  },
  setMovieTaskState({commit}, taskState){
    commit('Set_Movie_Task_State', taskState)
  }
}

export default
{
  namespaced: true,
  state,
  actions,
  mutations
}

permission.js

router.afterEach((to, from) => {
  // finish progress bar
  switch (from.path.split('/').pop()) {
    case 'movie':
      // 如果是电影界面
      if (!store.getters.movieSocket.taskState) {
        // 如果没有任务正在执行则断开连接
        store.dispatch('socket/disconnectMovie').then(()=>{
        })
      }
      break
  }
  NProgress.done()
})

index.js

{
        path: 'movie',
        name: 'Movie',
        beforeEnter(to, from, next) {
          if (!store.getters.movieSocket.socket) {
            // 如果没有建立websocket连接则建立连接
            connect.connectMovieSocket()
          }
          next()
        },
        component: () => import('@/views/movie/index'),
        meta: {title: '电影', icon: 'el-icon-film'}
      },

movie/index.vue

created() {
      this.$store.getters.movieSocket.socket.onmessage = (response) => {
        this.responseData = JSON.parse(response.data)
        this.code = this.responseData.code
        switch (this.code) {
          case 200:
            this.buttonContent = '日志查看'
            this.$store.getters.movieSocket.taskState = ''
            this.searchResult = this.responseData.data.result
            this.total = this.responseData.data.total
            this.loadText = "正在从数据库中获取结果"
            this.loading = false
            break
          case 204:
            this.$store.getters.movieSocket.taskState = 1  // 更新websocket的任务状态
            this.loading = false
            this.buttonContent = '当前任务'  // 切换按钮的text
            this.currentLog = this.responseData.data.result.join("\n") // 显示当前爬虫日志
            this.log = this.currentLog
            // this.ref$['taskButton'].text = '任务查看'
            // this.loadText = "正在从网页重新爬取结果"
            // this.loading ? '' : this.loading = true
            break
          case 500:
            this.loading = false
            this.$message({
              message: "请求出错",
              type: "danger"
            })
            break
        }
      }
      this.getList()
    },

 

这样在每次进入电影界面之前就会自动连接websocket.效果如下:

详细的代码和注册可以查看我的github: https://github.com/JustKeepSilence/DownLoad,欢迎大家交流和讨论~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
aiohttpwebsocket是一种异步实现的方式,可以实现实时向客户端推送最新的数据。在使用aiohttpwebsocket时,可以通过以下代码来处理websocket连接: ```python async def websocket_handler(request): ws = web.WebSocketResponse() await ws.prepare(request) # 等待websocket连接 async for msg in ws: if msg.type == aiohttp.WSMsgType.TEXT: if msg.data == 'close': await ws.close() else: await ws.send_str(msg.data + '/answer') elif msg.type == aiohttp.WSMsgType.ERROR: print('ws connection closed with exception %s' % ws.exception()) print('websocket connection closed') return ws ``` 这段代码会等待websocket连接,并在接收到消息时进行处理。如果收到的消息是文本类型,可以根据具体的业务逻辑进行处理,比如发送回复消息。如果收到的消息类型是错误,可以进行相应的处理。最后,当websocket连接关闭时,会打印相应的信息并返回websocket对象。\[2\] #### 引用[.reference_title] - *1* *2* [3.aiohttpwebsocket使用](https://blog.csdn.net/qq_39778055/article/details/107161749)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [使用python+aiohttp还原某度某吧私信的websocket+protobuf+RSA/AES加密流程](https://blog.csdn.net/weixin_43044226/article/details/125455758)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值