教你如何用nodejs爬掘金(一)

前言,此文章僅做教學用途,若是有人拿去幹別的事情,我概不負責,若是該文章侵害到了掘金社區的利益,請膜法小編馬上聯繫我刪除.node

這是我在掘金的第一篇文章,遂想寫個爬蟲教程吧,目標就是掘金,嘿嘿git

本文用到的三個工具爲

  • cheerio:jQuery語法,幫助你在非瀏覽器環境下解析網頁用的
  • qs 序列化成url的查詢字符串,(不知道說沒說對...)例:{a:1,b2} => a=1&b=2
  • request 一個封裝好的好用的請求庫,我本身把它promise化了一下

所有代碼見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編碼

獲取token

打開相關網站,嘗試解碼

答案呼之欲出啊,最重要的三個參數全在這了,那麼問題來了,node如何解析base64編碼呢?

一行代碼解決,buffer對象自己提供了base64的解碼功能,最後調用toString方法,轉成字符串,最後parse獲得對象

buffer用法淺析nodejs的buffer類

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了 ◔ ‸◔?

以上代碼或言論若有錯誤,還望你們指出

最後,我要吐槽一句編輯器,竟然不支持粘貼圖片???

相關文章
相關標籤/搜索