前段時間看的爬蟲都是不須要登陸直接爬取數據,這回就試試爬取須要登陸的網站信息吧,說幹就幹,直接就拿segmentfault作爲目標!html
咱們首先用chrome或者其餘瀏覽器打開segmentfault的主頁,找到它的登陸接口,點擊登陸接口,記得把Preserve log勾上,不然跳轉以後找不到接口,如圖(重要信息打了馬賽克):node
顯而易見這是一個post請求,三個參數分別是用戶名、密碼、和是否記住密碼的標記。git
仔細看請求頭header
裏的cookie
,在請求發送的時候就已經有了,咱們直接把整個請求頭拿過來,就直接用圖中的接口和header
登陸,逐一刪除cookie
中的項,測試登陸結果,最終發現只有PHPSESSID
是必須的。這個PHPSESSID
如何獲取呢?咱們能夠在登陸以前先訪問segmentfault
主頁,將返回的cookie
拿到,再在登陸的時候加上這個cookie
便可。
獲取cookie的代碼以下:github
(cb) => { superagent .get('https://segmentfault.com') .end((err, res) => { if (err) console.log(err) cookie = res.headers['set-cookie'].join(',').split(';')[0] // 獲取PHPSESSID cb(null) }) }
還有一個參數須要注意:接口中的Query String Paramsters
的_
參數,那麼這個參數是怎麼來的呢?在返回的response
的header
裏尋找並無找到它的蹤影,因此猜測它應該是隱藏在源碼裏,咱們直接在chrome
控制檯的source
下全局搜索_=
(source
頂部右鍵選擇search in all files
便可出現全局搜索框),逐一排查可能性:ajax
排查過程當中發現箭頭所指的ajaxSend
函數好像和咱們須要的有關係:它緊鄰的下面的delegate
函數內容應該就是登錄有關的內容,經過/api/user/?do=login
和submit
等就能夠清楚的看出,這個函數中的url
是從n.attr('action')
拿到的,猜想這個n.__
確定和請求中的Query String
參數脫不了關係。正好這個ajaxSend
函數中就有n.__
,也正好驗證了咱們剛纔的推測,分析這行代碼:chrome
n.url.indexOf("?") === -1 ? n.url = n.url + "?_=" + i._ : n.url = n.url + "&_=" + i._
n.url
默認是n.url + "?_=" + i._
,那麼這個i.__
應該就是最終boss,就在這個文件中找到定義i
的代碼,如上圖箭頭所指,繼續全局搜索SF.token
,最終在index.html
中找了生成它的代碼,包含在一個script
中,如圖:segmentfault
找到來源就簡單了,咱們仍然是在登陸直接先訪問主頁,將整個主頁的html代碼拿到,而後將這個script的內容取出來不就好了,哈哈,好開心~
獲取script的代碼以下:api
var cheerio = require('cheerio') function getRandom(s) { let $ = cheerio.load(s) let script = $('script').eq(8).html() let fn = new Function('window', script + ';return window.SF.token') let token = fn({}) $ = null return token } exports.getRandom = getRandom
到這裏,登陸就算完成了一大半了,接下來就是簡單的用superagent
調用接口啦,這裏的請求頭出了cookie
的其餘部分也是必需要設置的,能夠直接從瀏覽器上copy下來,代碼以下:瀏覽器
(cb) => { const username = process.argv[2] const password = process.argv[3] console.log(cookie) console.log(random) let header = { 'accept': '*/*', 'accept-encoding': 'gzip, deflate, br', 'accept-language': 'zh-CN,zh;q=0.9', 'content-length': '47', 'content-type': 'application/x-www-form-urlencoded; charset=UTF-8', 'cookie': `PHPSESSID=${cookie};`, 'origin': 'https://segmentfault.com', 'referer': 'https://segmentfault.com/', 'user-agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36', 'x-requested-with': 'XMLHttpRequest' } superagent .post(`https://segmentfault.com/api/user/login`) .query({'_': random}) .set(header) .type('form') .send({ username: username, password: password, remember: 1 }) .end(function(err, res) { if (err) { console.log(err.status); } else { console.log('返回狀態碼: ' + res.status) cb(null) } }) },
終於返回200了,美滋滋,而後咱們繼續~好比我我想用代碼修改我的主頁的我的描述內容,首先咱們先找到相關接口,如圖:
cookie
這個post請求的參數description就是我的描述的所填寫的新的內容,咱們直接用superagent調用這個接口
(cb) => { superagent // 編輯右上角我的說明 .post('https://segmentfault.com/api/user/homepage/description/edit') .query({'_': random}) .set(header) .type('form') .send({ description: '努力coding的小喵~~~' }) .end((err, res) => { if(err) throw err let result = JSON.parse(res.text) if (result.status === 0) { console.log('編輯成功') } else { console.log('編輯失敗:' + result.data) } }) cb(null, 1) }
返回狀態碼200,而後直接去瀏覽上的主頁刷新下,能夠看到我的描述的內容已經成功更新了!
segmentfault
主頁並登錄,找到登陸請求的接口並分析node
登陸以前,先請求主頁接口,目的是拿到PHPSESSID
和源代碼中的生成Query String
的函數整個登陸過程耗費了好久的時間,有空就研究這個Query String
的來源,好不容易登陸成功想幹點事情,又沒注意到設置請求頭,覺得是sf_remember
參數的問題,又折騰了許久,還好,最終總算是成功了!感謝本身的不放棄~
github地址:https://github.com/fighting12...