[Node] 爬蟲學習筆記
目錄
[TOC]
常用套件
- Request @ GitHub
- Cheerio
- Async
- Nightmare.js
- Puppeteer.js
npm install request cheerio async puppeteer
重要觀念
- 對於 http 來說,每次的 request 都是 stateless,也就是說,在這個 request 裡面肯定有某樣東西是驗證我們為已登入狀態。
- 有非預期的結果,或者 Postman 和 Browser 拿到的結果不同時,很有可能是 Cookie 的影響,這時候重新載入(Ctrl + R)可能沒效,可以透過清除網站資料的方式試試。
- postman 每次發出 request 後也會留有 cookie 紀錄,記得把它清除:
一些重要的 Response Headers 屬性
在 Response Headers 中:
Location
:告訴瀏覽器要轉址,通常會在 304 Found 之後給予要轉址的路徑,瀏覽器會自動轉址。Set-Cookie
:透過這 個屬性可以在瀏覽器中設置 Cookie ,而 Cookie 預設會自動帶入下一次的 Request Headers 中。
取得 Response Headers 中的 Cookie
如過是使用 requestJS 的話,可以透過 res.headers['set-cookie']
取得 Set-Cookie
的內容:
request('url', (err, res, body) => {
let Cookie = res.headers['set-cookie']
})
9-1 get-comics
keywords: 解碼
這篇比較有技術內容,因為它的圖片有加密,所以特別留筆記補充。
首先透過 inspector 點選圖片會發現 <div id="iBody"></div>
這段:
但是這段在透過 Postman 取得時並不存在,表示他是透過 JS 重新轉譯的:
可以看到在這個 <div>
附近包了兩個 function 分別是 window_onload()
和 dfImg()
。
從 <head></head>
去找可以看到 分別載入了 view.js
和 ajaxClass.js
,看了一下內容,可以發現這兩個 function 藏在 view.js
中:
接著可以在 Chrome Inspector 中的 Sources
中找到這支檔案:
其中在 window_onload()
這個 function 中可以找到 unsuan
function ,這是用來解碼圖片網址的函式:
Watch Video @ Youtube
雖然可以透過 debugger
的方式進入這個函式,而且也可以直接在 console 中使用 unsuan
這個函式,但是卻找不到這個函式藏在哪裡。
原來它藏在 view.js
的最上面,經過一些特殊的編碼試圖混淆我們,讓我們找不到:
把整段貼入 console 中就可以把它打回原形了:
而圖片的網址則藏在 <img>
的 name
屬性中:
10-1 ibon-upload(mobile)
keywords: 檔案上傳
, file upload
這篇要注意的是:
- 要先透過
getASPNetToken()
取得 ASP.NET 特定使用的 Token sendFile()
之後的 response header 中有一個Set-Cookie
屬性,裡面有ASP.NET_SessionId
,必須把這個 Cookie 往後帶到getFileCode()
的 header 中,才能正確取得檔案編碼:
10-2 ibon-upload(web)
這篇要注意的是
- 要先透過
getASPNetToken()
取得 ASP.NET 特定使用的 Token,和手機版不同之處是,Cookie 中的ASP.NET_SessionId
需樣打另一道網址才會取得:
- 另外電腦版要記得把 Cookie 清掉,才能看到 Set-Cookie 的 Header
12-2 get-fb-friends-birthday
- FB 傳會來的 response 會以
for (;;);'{ ... }
開頭,先把它移除,後面會是 JSON 物件 - html 的 template 會藏在
JSON.parse(body.replace('for (;;);', '')).domops[0][3].__html
裡面 - 其中裡面的文字透過 HTML encode 和 URI encode 過,因此需要先盡進行 HTML decode 接著進行
decodeURIComponent
才可以看到「看的懂」的中文和 HTML。
經過 HTML decoder 後才可以看到中文:
接這透過 decoderURIComponent
可以轉換成可使用的 HTML:
最後透過 chrome console 中右下角的複製貼到編輯器中排版:
[Unit14] ithelp-oauth-login
由於每次 response 回來的 Headers 中大多帶有 set-cookie
指令,因此使用餅乾盒的概念({jar: true}
),把每一次去得的 cookie 都帶到下一次使用會比較方便:
const request = require('request').defaults({ jar: true });
14-1 iThelp 登入
在 clickLoginFromIThelp()
的時候,從 Postman 帶回來的 header 可以直接看到 Location
並且沒有 <body>
;但是透過 Node 的 requestJS 會帶有 <body>
,而原本的 Location 則會藏在 res.request._redirect.redirects
當中。
function clickLoginFromIThelp(callback) {
request('https://ithelp.ithome.com.tw/users/login', (err, res, body) => {
let redirectLocation = res.req._headers.referer;
console.log('LocationInResponse', LocationInResponse);
});
}
14-2 Get "Code" for callback and "LOGIN" Cookie
在 14-2 Get "Code" for callback and "LOGIN" Cookie 可以取得兩個重要的 Cookie ITHOME_LOGIN
和 laravel_session
需要帶到後面的 request 使用:
在 Body 中也可以取得所需要的 code
14-3 取得 OAuth set-cookie 中的 Token
將 14-2 的 Cookie 和 code 帶入後,可以在 Set-Cookie
中看到非常重要的 _token
:
但要留意的是,一組 code 只能用一次 ,如果使用過取得 _token
之後,再次發送此 request,只會取得 404 Not Found,此時只能回到 14-2 重新取得一次新的 code:
14-4 成功登入
接著把 14-3 中的兩個重要 Cookie _token
和 ithelp2016_desktop
帶入這個 request 中,即可成功登入 ithelp。
參考
- 爬蟲始終來自於惰性 @ iThome
- 工欲善其事,必先利其器(下) @ iThome 爬蟲始終來自於墮性