前言,此文章僅做教學用途,若是有人拿去幹別的事情,我概不負責,若是該文章侵害到了掘金社區的利益,請膜法小編馬上聯繫我刪除.node
這是我在掘金的第一篇文章,遂想寫個爬蟲教程吧,目標就是掘金,嘿嘿git
所有代碼見githubgithub
開始我是嘗試直接請求掘金首頁,而後用cheerio解析,而後拿到網頁繼續幹活的。。但是事情並無這麼簡單,經過這個方法爬取的網頁跟咱們正常瀏覽的首頁不同(有多是我哪姿式不對) 沒辦法,只能從接口出發了web
首先打開網頁版掘金, 而後打開chrome的network,查看相關請求chrome
咦!recommend?推薦?好了,進去一看,果真是首頁熱門文章,可是。。。 請求參數suid是什麼?查看請求調用堆棧,,再看源碼,emmmm 源碼已經被混淆壓縮了這可怎麼辦?我沒有登錄 查看完全部請求響應都沒看到跟suid有關的,這可咋整?數據庫
直接進入請求網址,再更改suid,發現隨便更改均可以獲得相應 可是。。。這並無什麼用啊!就10條信息還須要爬嗎?json
沒辦法了,只能老套路了。先登錄再說promise
爲了防止頁面跳轉後登錄請求消失,須要先勾選Preserve log,使頁面跳轉後前面的請求不會消失瀏覽器
差點忘打碼了,qwqbash
let data = await request.create({
url: 'https://juejin.im/auth/type/email',
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({email: '155com', password: 'cfdsd.'}) //帳號密碼
});
複製代碼
直接一個請求搞定,獲得以下相應,問題的關鍵就在於cookie
好了,接下來該找接口了,點擊最新,發現network多了下面這個請求,其響應數據就是最新板塊的文章
相關參數有來源,設備id,用戶id,token等,其中最重要的就是token,id什麼的隨便改兩個字符好像也沒問題,可是token錯了它會報illegal token,請求方法錯了,就算參數對了也會報missing src。當你看到token的時候,你會發現,哪都找不到這個數據
可是你仔細看第5張圖的時候,你會發現這auth後面這串字符很像base64編碼
打開相關網站,嘗試解碼
答案呼之欲出啊,最重要的三個參數全在這了,那麼問題來了,node如何解析base64編碼呢?
一行代碼解決,buffer對象自己提供了base64的解碼功能,最後調用toString方法,轉成字符串,最後parse獲得對象
const cookie = data.headers['set-cookie'];
const encodeToken = cookie[0]
.split(';')[0]
.split('=')[1];
const decodeToken = JSON.parse(new Buffer(encodeToken, 'base64').toString())
複製代碼
有了token,你就能夠爲所欲爲的爬了,爬圖片?主題?標題?文章內容?徹底o98k
async function getPictureUrl(request, url) {
let data = await request.get({ url });
console.log(data.body.match(/(https:\/\/user-gold-cdn).+?\/ignore-error\/1/g)); //匹配出圖片url,這裏掘金使用了cdn來存儲圖片
}
複製代碼
async function getTopics(request, typeKey) {
const { token, clientId, userId } = require('./user.json');
const querystring = qs.stringify({
src: 'web',
uid: userId,
device_id: clientId,
token: token,
limit: 20,
category: 'all',
recomment: 1
});
const types = {
timeline: 'get_entry_by_timeline', //最新
comment: 'get_entry_by_comment', //評論
rank: 'get_entry_by_rank' //熱門
};
const data = await request.get({
url: `https://timeline-merger-ms.juejin.im/v1/${types[typeKey]}?${querystring}`,
headers: {
host: 'timeline-merger-ms.juejin.im',
referer: 'https://juejin.im/timeline?sort=comment'
}
});
const body = data.body;
if (body.s !== 1) { //出錯時清空信息
fs.writeFileSync('./user.json', JSON.stringify({}));
throw { type: 'token', message: body.m };
} else {
return body.d.entrylist;
}
}
複製代碼
try {
(async function() {
const request = new Riven();
request.setDefaultOptions({
headers: {
Cookie:
'gr_user_id=44868117-2a80-49e8-ba2b-2acd2a77a887; ab={}; _ga=GA1.2.1234597644.150' +
'6904166; MEIQIA_EXTRA_TRACK_ID=0uMtBISQ3EoiMICJMjpaZedfTBz; _gid=GA1.2.100579701' +
'2.1523672771; Hm_lvt_93bbd335a208870aa1f296bcd6842e5e=1521573516,1521573752,1522' +
'270605,1523672771; gr_session_id_89669d96c88aefbc=d54a635e-cece-4f16-aca4-808ae9' +
'2ee559; gr_cs1_d54a635e-cece-4f16-aca4-808ae92ee559=objectId%3A5a974f6ef265da4e8' +
'53d8d52; auth=; auth.sig=25Jg_aucc6SpX1VH8RlCoh6azLU; Hm_lpvt_93bbd335a208870aa1' +
'f296bcd6842e5e=1523675329; QINGCLOUDELB=165e4274d6090771b096025ed82d52a1ab7e48fb' +
'3972913efd95d72fe838c4fb|WtFwy|WtFwr'
}
}); //設不設置cookie都OK的
if (!isLogin()) {
login(request);
}
const topics = await getTopics(request, 'commnet');
for (let i = 0; i < topics.length; ++i) {
//await getDetailData(request, topics[i].objectId);
getPictureUrl(request, topics[i].originalUrl);
await sleep(2000); //僞線程掛起
}
})();
process.on('unhandledRejection', error => {
if (error.type === 'token') {
login();
}
console.log(error.message);
});
} catch (error) {
console.log(error.message);
}
複製代碼
固然,我沒有使用數據庫來保存數據,這只是教你們爬取原理,到這裏,一個超級簡單的爬蟲就完成了
到最後好像也沒用到cheerio了 ◔ ‸◔?
以上代碼或言論若有錯誤,還望你們指出
最後,我要吐槽一句編輯器,竟然不支持粘貼圖片???