雨課堂模擬登錄_獲取websocket數據


寫在最前:互聯網並非法外之地,爬蟲僅供技術交流

運行環境

  • python 3.7.4
  • requests 2.10.0
  • numpy 1.17.2
  • opencv-python 4.2.0.34

爬取目標

  • 模擬登錄雨課堂

雨課堂目前的登錄流程

這次想跟大家分享一下websocket協議的爬蟲怎么做。我們以雨課堂的掃碼登錄為例。

雨課堂掃碼登錄的流程是

  1. https://www.yuketang.cn/web?next=/v2/web/index&type=3頁面加載完畢后,客戶端與服務端建立websocket鏈接。
  2. 隨即客戶端發送一段數據,用於請求微信二維碼。
  3. 服務端拿到數據后反饋二維碼相關信息。
  4. 並每隔一段時間重新發送一次二維碼信息(我記得之前測試的時候是這樣的,但是最近好像都需要客戶端重發,服務端才回饋啊,那這樣用websocket的意義何在)。
  5. 客戶端根據信息去請求二維碼圖片。
  6. 用戶掃碼,由移動客戶端發送信息至服務端確認用戶正在登錄。
  7. 服務端再通過websocket發送登錄的相關信息回客戶端。
  8. 客戶端拿到登錄的相關信息后post到login接口進行登錄,至此登錄成功。

具體步驟

一、找到websocket接口

雨課堂的websocket接口為wss://www.yuketang.cn/wsapp/

headers其實可以不帶,雨課堂好像沒有做相關鑒權。之前好像看到網上有說要帶Sec-WebSocket相關屬性的headers,其實不用啊,這個使用websocket就會自動生成。

二、查看websocket數據交流情況

數據 時間
WebSocket 連接已建立 1602385999.188397
{"op":"requestlogin","role":"web","version":1.4,"type":"qrcode","from":"web"} 1602385999.4041245
{"op":"requestlogin","loginid":19xxx22,"expire_seconds":60,"ticket":"https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=xxxxxxxxx","qrcode":"http://weixin.qq.com/q/xxxxxxxxx"} 1602385999.4143353

第二行(不包含表頭)的數據就是我們需要發給客戶端的。

第三行就是他會反饋的數據,隱私信息已經打碼。

ticket就是登錄二維碼的鏈接啦。

可以下載到本地然后用PIL這個庫顯示出來,用手機掃碼,服務端就會通過websocket鏈接發送如下數據給我們。

{"subscribe_status":true,
 "AppOpenID":"打碼",
 "profile_edit_status":true,
 "UserID":"打碼",
 "DateJoined":"2019-04-30T13:31:55",
 "Role":2,
 "LastLogin":"2019-04-30T13:34:18",
 "Department":"",
 "WeixinUnionID":"打碼",
 "LastLoginIP":"打碼",
 "noRecArticle":true,
 "Auth":"打碼",
 "ppt_config_data":{},
 /*姓名、性別、年齡、頭像、位置等相關信息已經全部刪除*/
 "Language":"zh-cn",
 "is_self_set":false,
 "MinaOpenID":"",
 "isBind":true,
 "user_on_lessons":[],
 "AndroidOpenID":"",
 "op":"loginsuccess",
 "loginid":"打碼"}

關鍵信息就是里面的UserID和Auth,是接下來登錄的關鍵。

三、登錄

我們要先去GET這個鏈接https://www.yuketang.cn/v/course_meta/user_info獲取一個csrftoken。

接着就可以將之前獲得的UserID和Auth POST到https://www.yuketang.cn/pc/web_login獲取sessionid,至此登錄成功。

具體的代碼

import requests
import websocket
import json
import cv2 as cv
import numpy as np

userinfo = {}
session = requests.session()

def on_message(ws, message):
    global userinfo
    userinfo = json.loads(message)
    if 'subscribe_status' in userinfo:
        ws.close()
        return
    req = session.get(userinfo['ticket'])
    cv.namedWindow('input_image', cv.WINDOW_AUTOSIZE)
    cv.imshow('input_image', cv.imdecode(np.array(bytearray(req.content), dtype='uint8'), cv.IMREAD_UNCHANGED))
    cv.waitKey(0)
    cv.destroyAllWindows()
def on_error(ws, error):
    print(error)
def on_open(ws):
    ws.send(data=json.dumps({"op":"requestlogin","role":"web","version":1.4,"type":"qrcode","from":"web"}))
		print("open")

# websocket數據交互
ws = websocket.WebSocketApp("wss://www.yuketang.cn/wsapp/",
                                on_message = on_message,
                                on_error = on_error)
ws.on_open = on_open
ws.run_forever()

# 登錄
req = session.get("https://www.yuketang.cn/v/course_meta/user_info")
session.post("https://www.yuketang.cn/pc/web_login",data=json.dumps({'UserID':userinfo['UserID'],'Auth':userinfo['Auth']}))

# 獲取自己的課程列表
req = session.get("https://www.yuketang.cn/v2/api/web/courses/list?identity=2")
print(json.loads(req.content))


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM