boss直聘聊天機(jī)器人

想轉(zhuǎn)崗到爬蟲工程師辕翰,由于面試機(jī)會(huì)太少夺衍,而boss直聘又無法海投,決定做一個(gè)boss直聘機(jī)器人來幫我找工作喜命。

一沟沙、基本需求

  1. 一個(gè)爬蟲程序爬取需要的工作信息,存入數(shù)據(jù)庫壁榕。
  2. 聊天機(jī)器人每天上午10點(diǎn)向未聊天的boss打招呼矛紫。
  3. 如果有boss回復(fù)了,聊天機(jī)器人向boss發(fā)送簡歷(因?yàn)閎oss直聘設(shè)定必須雙方說話過后才能發(fā)簡歷)牌里。

二颊咬、涉及知識(shí)點(diǎn)

  1. protobuf
  2. MQTT
  3. websocket

三、聊天機(jī)器人實(shí)現(xiàn)過程

1. 查看boss直聘網(wǎng)頁版即時(shí)通訊實(shí)現(xiàn)方式牡辽。

查看聊天界面ws下有無建立websocket喳篇。


image.png

發(fā)現(xiàn)無websocket建立,考慮難道是ajax輪訓(xùn)不會(huì)這么low吧态辛?
但是在與別人聊天時(shí)候麸澜,下面并無新增ajax請求。
打開抓包工具charles進(jìn)行抓包查看奏黑。


image.png

發(fā)現(xiàn)是有ws建立的炊邦。改用chrome瀏覽器编矾,
image.png

可以看到是有ws建立。(第一個(gè)坑馁害,以后默認(rèn)使用chrome瀏覽器)窄俏。

2.websocket連接建立方式及參數(shù)

查看連接建立的調(diào)用棧


image.png

將關(guān)聯(lián)的js都下載到本地,使用webstorm格式化代碼碘菜。再使用charles的map local功能將這三個(gè)文件代理凹蜈。這樣boss直聘使用的js就是本地格式化后的代碼了(否則在使用查看調(diào)用時(shí),所有代碼都堆在2行炉媒,不可讀)踪区。
仔細(xì)查看調(diào)用堆棧確認(rèn)是app.js的connection處傳入的連接參數(shù)。


image.png

搜索關(guān)鍵詞paho-mqtt了解mqtt的功能吊骤。所以boss直聘是使用的paho.mqtt這個(gè)第三方庫缎岗。
在本地使用paho.mqtt第三方庫做個(gè)連接的demo。參數(shù)通過修改app.js白粉,在建立連接前打印所有的參數(shù)獲得传泊。

代碼:

        var hostname = 'ws.zhipin.com', //'192.168.1.2',
            port = 443,
            ssl = true,
            topic = '/chatws';
        client = new Paho.MQTT.Client(hostname, port, topic, "ws-CD090DC8307DE0AC");
        //建立客戶端實(shí)例
        var options = {

            password: "Xxxxxx",
            userName: "Xxxxxxxx",
            useSSL: ssl,
            onSuccess: onConnect,
            onFailure: function (e) {
                console.log(e);
            }
        };
        client.connect(options);
        //發(fā)送消息  
        message = new Paho.MQTT.Message("hello");  
        message.destinationName = topic;  
        client.send(message);

運(yùn)行后:


image.png

連接已經(jīng)可以建立。但是在發(fā)送信息后鸭巴,會(huì)報(bào)錯(cuò)并斷開連接眷细。因?yàn)閿?shù)據(jù)格式有誤。

3鹃祖、通信數(shù)據(jù)格式

websocket連接已經(jīng)可以建立溪椎,接下來就是查看boss直聘的通信數(shù)據(jù)格式了。
通過charles抓包恬口,取到當(dāng)我對一個(gè)boss發(fā)送“你好”時(shí)的數(shù)據(jù):

3357 0004 6368 6174 0001 0801 1A4B 0A02 0800 1220 0800 121C 3531 6465 3762 6632 6234 3732 6139 3566 3148 525F 3039 5739 4556 6F7E 1801 20EE FBC8 FB92 2D28 B8B7 8EF2 922D 320C 0801 1001 1A06 E4BD A0E5 A5BD 58EE FBC8 FB92 2D

簡單的16進(jìn)制轉(zhuǎn)字符串后獲得:

3W?chat???K
?? ??51de7bf2b472a95f1HR_09W9EVo~?? ?????-(????-2?????你好X?????-

這不是一個(gè)簡單的json數(shù)據(jù)校读,查看數(shù)據(jù)發(fā)送時(shí)的調(diào)用堆棧


image.png

發(fā)現(xiàn)protobuf.js關(guān)鍵字,搜索并學(xué)習(xí)了protobuf祖能。通過打印發(fā)送的數(shù)據(jù)歉秫。


image.png

獲得數(shù)據(jù):
        [8, 1, 26, 75, 10, 2, 8, 0, 18, 32, 8, 0, 18, 28, 53, 49, 100, 101, 55, 98, 102, 50, 98, 52, 55, 50, 97, 57, 53, 102, 49, 72, 82, 95, 48, 57, 87, 57, 69, 86, 111, 126, 24, 1, 32, 233, 193, 149, 232, 145, 45, 40, 179, 253, 218, 222, 145, 45, 50, 12, 8, 1, 16, 1, 26, 6, 228, 189, 160, 229, 165, 189, 88, 233, 193, 149, 232, 145, 45]

寫一個(gè)使用protobuf轉(zhuǎn)化的demo。

var protobuf = require("protobufjs");

protobuf.load("proto.proto")
    .then(function (root) {
        var Protocol = root.lookupType("TechwolfChatProtocol");
        // var data = Buffer.from([8,2,34,87,8,1,16,182,196,186,9,26,76,10,0,18,0,26,0,34,0,42,18,49,53,53,48,56,49,55,53,57,51,55,49,49,49,52,53,50,53,50,12,53,57,46,49,48,57,46,55,55,46,57,52,56,187,70,66,3,119,101,98,74,2,45,49,82,0,90,0,97,0,0,0,0,0,0,0,0,105,0,0,0,0,0,0,0,0,40,0]);
        var data = Buffer.from([8, 1, 26, 75, 10, 2, 8, 0, 18, 32, 8, 0, 18, 28, 53, 49, 100, 101, 55, 98, 102, 50, 98, 52, 55, 50, 97, 57, 53, 102, 49, 72, 82, 95, 48, 57, 87, 57, 69, 86, 111, 126, 24, 1, 32, 233, 193, 149, 232, 145, 45, 40, 179, 253, 218, 222, 145, 45, 50, 12, 8, 1, 16, 1, 26, 6, 228, 189, 160, 229, 165, 189, 88, 233, 193, 149, 232, 145, 45]);
        // Decode an Uint8Array (browser) or Buffer (node) to a message
        var message = Protocol.decode(data);
        console.log(message);

    });
打印數(shù)據(jù)為:
TechwolfChatProtocol {
  messages:
   [ TechwolfMessage {
       from: [TechwolfUser],
       to: [TechwolfUser],
       type: 1,
       mid: [Long],
       time: [Long],
       body: [TechwolfMessageBody],
       cmid: [Long] } ],
  messageSync: [],
  messageRead: [],
  type: 1 }

可以解析數(shù)據(jù)养铸。這樣數(shù)據(jù)格式就找到了雁芙。

4、發(fā)送一條消息钞螟。

考慮node運(yùn)行聊天機(jī)器人兔甘,但是 paho-mqtt.js不支持node方式,僅支持瀏覽器鳞滨。而python同時(shí)支持paho-mqtt和protobuf裂明。
所以使用python來結(jié)合完成。
但是在python中建立socket連接時(shí)總會(huì)報(bào)錯(cuò):


image.png

給出了報(bào)錯(cuò),但是沒有具體信息闽晦。以為是tls版本太低,最后在mqtt源碼報(bào)錯(cuò)處添加打印提岔,獲得信息

b"bytearray(b'http/1.1 403 forbidden\\r\\n')"
b"bytearray(b'date: wed, 27 feb 2019 10:03:06 gmt\\r\\n')"
b"bytearray(b'transfer-encoding: chunked\\r\\n')"
b"bytearray(b'connection: keep-alive\\r\\n')"

發(fā)現(xiàn)是在websocket握手時(shí)仙蛉,http請求直接403了,考慮是否與cookies有關(guān)碱蒙,在源碼找到header設(shè)置的地方荠瘪,添加cookies參數(shù)。
運(yùn)行后可以正常連接赛惩。
結(jié)合protobuf后哀墓,最終代碼:

chat = {
    'type': 1,
    'messages': [
        {
            'from': {'uid': 0},
            'to': {'uid': 0, 'name': 'xxxxxxxxx~'},#name為boss的id
            'type': 1,
            'mid': 1550970085609,
            'time': 1550950252211,
            'body': {'type': 1, 'templateId': 1, 'text': '你好'},
            'cmid': 1550970085609
        }
    ]
}
chat_protocol = protobuf_json.json2pb(TechwolfChatProtocol(), chat)

hostname = 'ws.zhipin.com'
port = 443
clientId = '19833398'
timeout = 60
keepAlive = 100
topic = '/chatws'

# The callback for when the client receives a CONNACK response from the server.
def on_connect(client, userdata, flags, rc):
    print("Connected with result code " + str(rc))

    # Subscribing in on_connect() means that if we lose the connection and
    # reconnect then subscriptions will be renewed.
    client.subscribe(topic)
    client.publish(topic,payload=chat_protocol.SerializeToString(),qos=0)


def on_disconnect(client, userdata, rc):
    if rc != 0:
        print("Unexpected disconnection.")

# The callback for when a PUBLISH message is received from the server.
def on_message(client, userdata, msg):
    print('received message -----'+client)
    protocol = TechwolfChatProtocol()
    protocol.ParseFromString(msg.payload)
    print(protocol)

client = mqtt.Client(client_id="ws-CD090DC8307DE0AC", clean_session=True,
                     transport="websockets")
client.username_pw_set("xxxxxxx", "xxxxx")  # 參數(shù)分別boss為用戶生的mqtt賬號密碼。
client.ws_set_options(path=topic)
client.tls_set()
client.on_connect = on_connect
client.on_message = on_message
client.on_disconnect = on_disconnect

client.connect(hostname, port, 60)
client.loop_forever()

運(yùn)行后喷兼,手機(jī)端以及可以看到給boss發(fā)送了“你好”篮绰。

5.總結(jié)

接下來只需要結(jié)合爬蟲,就可以完成最初的設(shè)想啦季惯。
完成這個(gè)聊天機(jī)器學(xué)到了protobuf吠各、mqtt、websocket相關(guān)的知識(shí)勉抓。
中間有卡殼的地方也很多贾漏。
但是一定要堅(jiān)信,web端所有的內(nèi)容藕筋,都是可爬的纵散。完成的所有功能,都是可以模擬的隐圾。
ps:
文章寫一半伍掀,就接到電話,有位大佬給推薦下工作了翎承。
再次感謝這位大佬硕盹。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市叨咖,隨后出現(xiàn)的幾起案子瘩例,更是在濱河造成了極大的恐慌,老刑警劉巖甸各,帶你破解...
    沈念sama閱讀 221,198評論 6 514
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件垛贤,死亡現(xiàn)場離奇詭異,居然都是意外死亡趣倾,警方通過查閱死者的電腦和手機(jī)聘惦,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,334評論 3 398
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來儒恋,“玉大人善绎,你說我怎么就攤上這事黔漂。” “怎么了禀酱?”我有些...
    開封第一講書人閱讀 167,643評論 0 360
  • 文/不壞的土叔 我叫張陵炬守,是天一觀的道長。 經(jīng)常有香客問我剂跟,道長减途,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,495評論 1 296
  • 正文 為了忘掉前任曹洽,我火速辦了婚禮鳍置,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘送淆。我一直安慰自己税产,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,502評論 6 397
  • 文/花漫 我一把揭開白布坊夫。 她就那樣靜靜地躺著砖第,像睡著了一般。 火紅的嫁衣襯著肌膚如雪环凿。 梳的紋絲不亂的頭發(fā)上梧兼,一...
    開封第一講書人閱讀 52,156評論 1 308
  • 那天,我揣著相機(jī)與錄音智听,去河邊找鬼羽杰。 笑死,一個(gè)胖子當(dāng)著我的面吹牛到推,可吹牛的內(nèi)容都是我干的考赛。 我是一名探鬼主播,決...
    沈念sama閱讀 40,743評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼莉测,長吁一口氣:“原來是場噩夢啊……” “哼颜骤!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起捣卤,我...
    開封第一講書人閱讀 39,659評論 0 276
  • 序言:老撾萬榮一對情侶失蹤忍抽,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后董朝,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體鸠项,經(jīng)...
    沈念sama閱讀 46,200評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,282評論 3 340
  • 正文 我和宋清朗相戀三年子姜,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了祟绊。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,424評論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖牧抽,靈堂內(nèi)的尸體忽然破棺而出嘉熊,到底是詐尸還是另有隱情,我是刑警寧澤阎姥,帶...
    沈念sama閱讀 36,107評論 5 349
  • 正文 年R本政府宣布记舆,位于F島的核電站,受9級特大地震影響呼巴,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜御蒲,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,789評論 3 333
  • 文/蒙蒙 一衣赶、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧厚满,春花似錦府瞄、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,264評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至丰榴,卻和暖如春货邓,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背四濒。 一陣腳步聲響...
    開封第一講書人閱讀 33,390評論 1 271
  • 我被黑心中介騙來泰國打工换况, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人盗蟆。 一個(gè)月前我還...
    沈念sama閱讀 48,798評論 3 376
  • 正文 我出身青樓戈二,卻偏偏與公主長得像,于是被迫代替她去往敵國和親喳资。 傳聞我的和親對象是個(gè)殘疾皇子觉吭,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,435評論 2 359

推薦閱讀更多精彩內(nèi)容

  • 網(wǎng)絡(luò)編程 1. 概論 建立連接:通過IP或者域名來連接兩臺(tái)設(shè)備,通過端口號找到對應(yīng)的通信程序 通信協(xié)議:要傳輸?shù)臄?shù)...
    陵無山閱讀 4,262評論 0 12
  • 點(diǎn)擊查看原文 Web SDK 開發(fā)手冊 SDK 概述 網(wǎng)易云信 SDK 為 Web 應(yīng)用提供一個(gè)完善的 IM 系統(tǒng)...
    layjoy閱讀 13,783評論 0 15
  • 有種片,不看沒事炸客,一看上癮适贸。 A級……自然歷史紀(jì)錄片。 自然風(fēng)光察署、人文科學(xué)盡收眼底闷游。 最值得羨慕的,還是其中的英雄...
    Sir電影閱讀 1,693評論 3 31
  • 晚休吠,我與父親行于街道之上,暢聊文學(xué)之事业簿。 街道瘤礁,昏暗,腳步走在砂石之上吱吱做響梅尤,寂冷柜思,寒風(fēng)而過瑟瑟發(fā)抖,凄靜巷燥,惟獨(dú)...
    又人同學(xué)閱讀 564評論 0 3
  • 繼續(xù)練習(xí)鋼筆字第158彈赡盘,今天介紹含有“心”字的字——想。 都無色可并缰揪,不奈此香何≡上恚瑤席乘涼設(shè),金羈落晚過钝腺∨坠茫回衾燈...
    胡義華閱讀 138評論 0 0