1. 程式人生 > >node爬蟲進階之——登入

node爬蟲進階之——登入

轉載自:http://www.jianshu.com/p/87867f325184

在之前的文章node入門場景之——爬蟲已經介紹過最簡單的node爬蟲實現,本文在原先的基礎上更進一步,探討一下如何繞過登入,爬取登入區內的資料

目錄

一、理論基礎

如何維持登入態

http作為一種無狀態的協議,客戶端和伺服器端之間不會保持長連線。在一個一個相互獨立的請求響應之間,伺服器如何識別哪些介面是來自同一個客戶端?聰明的你,很容易想到如下一種機制:


sessionId.png

這種機制的核心在於會話id(sessionId):

  1. 當客戶端請求伺服器端的時候,服務端判斷該客戶端沒有傳入sessionId,好的,這傢伙是新來的,給它生成一個sessionId,存入記憶體,並把這個sessionId返回客戶端
  2. 客戶端拿到伺服器端的sessionId儲存在本地,下次請求的時候帶上這個seesionId,伺服器檢查記憶體是否存在這個sessionId(如果在之前的某個步驟,使用者訪問了登入介面,那麼此刻記憶體中已經以seesionId為key,使用者資料為value儲存在了記憶體中),伺服器就可以根據sessionId這個唯一標識,返回該客戶端對應的資料
  3. 無論是客戶端還是伺服器端丟失了這個sessionId都會導致前面的步驟重新來過,誰也不認識誰了,重新開始

首先客戶端通過sessionId和伺服器端建立一種關聯,然後使用者再通過客戶端與伺服器端建立一種關聯(sessionId與使用者資料的鍵值對),從而維持了登入態

瀏覽器是怎麼做的

實際上,瀏覽器是不是按照上述的機制設計的呢?還真是!


bs-sid.png

這其中瀏覽器做了哪些事情:
一、 瀏覽器在每一次http請求中,都會在http的請求頭中加上該請求地址域名對應的cookie(如果cookie沒有被使用者禁用的話),在上圖中,第一個次請求伺服器請求頭中同樣有cookie,只是cookie中還沒有sessionId
二、 瀏覽器根據伺服器響應頭中的Set-Cookie設定cookie,為此,伺服器會將生成的sessionId放入Set-cookie中

瀏覽器接收到Set-Cookie指令,就會以請求地址的域名為key設定本地cookie,一般情況下,伺服器在返回Set-cookie的時候,對sessionId的過期時間預設設定為瀏覽器關閉時失效,這就是瀏覽器從開啟到關閉就是一次會話的由來(有些網站還可以設定保持登入,設定cookie長時間不失效爾爾)

三、 當瀏覽器再次向後臺發起請求時,此時請求頭中的cookie已經包含了sessionId,如果在此之前使用者已經訪問過登入介面,那麼就已經可以根據sessionId來查詢到使用者資料了

口說無憑,下面就以簡書為例說明:
1). 首先用chrome開啟簡書的登入頁面,在application中找到http://www.jianshu.com下的所有cookie,進入Network項中把preserve log勾選上(不然頁面發生了重定向之後將無法看到之前的log)


簡書登入

2). 然後重新整理頁面,找到sign-in介面,它的響應頭中有很多Set-Cookie有木有


簡書登入

3). 再去檢視cookie的時候,session-id已經儲存好了,下次再去請求簡書的其它介面的時候(例如獲取驗證碼、登入),都會帶上這個session-id,登入後用戶的資訊也會跟session-id關聯起來


簡書登入

二、node實現

我們需要模擬瀏覽器的工作方式,去爬去網站登入區內的資料
找了一個沒有驗證碼的網站進行試驗,有驗證碼的又要涉及到驗證碼識別(簡書的登入就不考慮了,驗證碼複雜程度感人),下節說明

訪問登入介面獲取cookie

    // 瀏覽器請求報文頭部部分資訊
    var browserMsg={
        "User-Agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.71 Safari/537.36",
        'Content-Type':'application/x-www-form-urlencoded'
    };

    //訪問登入介面獲取cookie
    function getLoginCookie(userid, pwd) {
        userid = userid.toUpperCase();
        return new Promise(function(resolve, reject) {
            superagent.post(url.login_url).set(browserMsg).send({
                userid: userid,
                pwd: pwd,
                timezoneOffset: '0'
            }).redirects(0).end(function (err, response) {
                //獲取cookie
                var cookie = response.headers["set-cookie"];
                resolve(cookie);
            });
        });
    }
  1. 需要現在chrome下捕獲一次請求,獲取一些請求頭的資訊,因為伺服器可能會對這些請求頭資訊進行校驗。例如,在我實驗的網站上,起初我並沒有傳入User-Agent,伺服器發現並不是來自伺服器的請求,返回了一串錯誤資訊,所以我之後設定User-Agent,把自己偽裝成chrome瀏覽器了~~

  2. superagent是一個 client-side HTTP request庫,使用它可以跟輕鬆的傳送請求,處理cookie(自己呼叫http.request在操作header欄位資料上就沒有這麼方便,獲得set-cookie之後,還得自己拼裝成合適的格式cookie)。redirects(0)主要是設定不進行重定向

請求登入區內介面

    function getData(cookie) {
        return new Promise(function(resolve, reject) {
            //傳入cookie
            superagent.get(url.target_url).set("Cookie",cookie).set(browserMsg).end(function(err,res) {
                var $ = cheerio.load(res.text);
                resolve({
                    cookie: cookie,
                    doc: $
                });
            });
        });
    }

在上一步中拿到set-cookie之後,傳入getData方法,在通過superagent設定到請求當中(set-cookie會格式化成cookie),就可以正常拿到登入去內的資料

在實際的場景中,未必會如此順利,因為不同的網站有不同的安全措施,例如:有些網站可能需要先請求一個token,有些網站需要對引數進行加密處理,有些安全性更高的,還有防重放機制。在定向爬蟲中,這需要具體的去分析網站的處理機制,如果繞不過去,就適可而止吧~~
但是對付一般內容資訊類的網站還是夠用的

通過以上方式請求到的只是一段html字串,這裡還是老辦法,使用cheerio庫將字串載入,就可以拿到一個類似於jquery dom的物件,就可以像jquery一樣去操作dom,這真的是一個神器,良心製作!

三、如果有驗證碼怎麼破

現在不需要輸驗證碼就可以登入的網站還有幾個?當然我們就不企圖去識別12306的驗證碼了,簡書這種良心之作驗證碼也不奢望了,像知乎這種too young too simple的驗證碼還是可以挑戰下的


知乎登入

Tesseract 是google開源的OCR識別工具,雖然跟node沒有什麼關係,但是可以用node來排程使用,具體使用方式:用node.js實現驗證碼簡單識別

能不能做到高識別率,就看人品了~~~

四、延伸

還有一種更簡單的方式去繞過登入態,就是使用PhantomJS,phantomjs是一個基於webkit開源的伺服器js api,可以認為它就是一個瀏覽器,只是你可以通過js指令碼來操控它。

由於其完全模擬瀏覽器的行為,所以你根本不需要關心set-cookie,cookie的事情,只需要模擬使用者的點選操作就可以了(當然如果有驗證碼,還是得去識別的)

這種方式也並非毫無缺點,完全模擬瀏覽器的行為,意味者不放過任何一個請求,需要載入可能你並不需要的js、css、圖片的靜態資源,需要點選多個頁面才能到達目的頁面,在效率上要比直接訪問target url要低

感興趣自行搜尋phontomJS

五、總結

雖然說的是node爬蟲的登入,但是前面原理講了一大堆,目的是如果你想換一種語言實現,也可以遊刃有餘,還是那句話:理解原理很重要

學習前端的過程中,我整理了很多資料,也希望能共享出來幫助到更多剛接觸或者接觸前端不久的同學。不過也為了把控微信群的質量,入群的一定要是前端的小夥伴才可以。入群我就會把資料發給每個人,每天也會挑選前沿的前端高質量文章發到群裡給大家學習。想加入的同學可以加笑笑微信:iamaixiaoxiao,拉你入群。再次強調,保證群高質量,群非前端不加,請諒解哦。掃描微信二維碼也可以。

相關推薦

node爬蟲——登入

轉載自:http://www.jianshu.com/p/87867f325184 在之前的文章node入門場景之——爬蟲已經介紹過最簡單的node爬蟲實現,本文在原先的基礎上更進一步,探討一下如何繞過登入,爬取登入區內的資料 目錄 一、理論基礎 如何維持登

那些年,我爬過的北科(四)——爬蟲極簡併行爬蟲框架開發

寫在前面 在看過目錄之後,讀者可能會問為什麼這個教程沒有講一個框架,比如說scrapy或者pyspider。在這裡,我認為理解爬蟲的原理更加重要,而不是學習一個框架。爬蟲說到底就是HTTP請求,與語言無關,與框架也無關。 在本節,我們將用26行程式碼開發一個簡單的併發的(甚至分散式的)爬蟲框架。 爬蟲的

爬蟲非同步協程

一、背景   之前爬蟲使用的是requests+多執行緒/多程序,後來隨著前幾天的深入瞭解,才發現,對於爬蟲來說,真正的瓶頸並不是CPU的處理速度,而是對於網頁抓取時候的往返時間,因為如果採用requests+多執行緒/多程序,他本身是阻塞式的程式設計,所以時間都花費在了等待網頁結果的返回和對爬取到的資料的寫

Python爬蟲程的用法

maxsize clas 生產 依然 queue consumer mac 裏的 filesize 前言 在上一節中介紹了thread多線程庫。python中的多線程其實並不是真正的多線程,並不能做到充分利用多核CPU資源。 如果想要充分利用,在python中大部分情況需要

【SSH路】Struts基本原理 + 實現簡單登入(二)

      上面博文,主要簡單的介紹了一下SSH的基本概念,比較巨集觀,作為初學者能夠有一個整體上的認識,個人認為對學習有很好的輔助功能,它不僅僅是一個“瞭望塔”,更是檢驗是否真正掌握所有內容的一個前

Python爬蟲url去重(可用於檔案去重)

主要介紹幾個常用和目前瞭解的,當然還有其他方法,這裡只說目前本人自己能實現的幾種方法的基本思想:基於Hash演算法的儲存。對每一個給定的URL,都是用一個已經建立好的Hash函式,對映到某個實體地址上。當需要進行檢測URL是否重複的時候,只需要將這個URL進行Hash對映,如

Python 爬蟲從入門到路(一)

通用爬蟲和聚焦爬蟲 根據使用場景,網路爬蟲可分為 通用爬蟲 和 聚焦爬蟲 兩種. 通用爬蟲 通用網路爬蟲 是 捜索引擎抓取系統(Baidu、Google、Yahoo等)的重要組成部分。主要目的是將網際網路上的網頁下載到本地,形成一個網際網路內容的映象備份。 通用

Python 爬蟲從入門到路(二)

上一篇文章我們對爬蟲有了一個初步認識,本篇文章我們開始學習 Python 爬蟲例項。 在 Python 中有很多庫可以用來抓取網頁,其中內建了 urllib 模組,該模組就能實現我們基本的網頁爬取。 在 Python2.x 和 Python3.x 中 urllib 模組是不一樣的,但是用法上差不多,我們先

Python 爬蟲從入門到路(三)

之前的文章我們做了一個簡單的例子爬取了百度首頁的 html,本篇文章我們再來看一下 Get 和 Post 請求。 在說 Get 和 Post 請求之前,我們先來看一下 url 的編碼和解碼,我們在瀏覽器的連結裡如果輸入有中文的話,如:https://www.baidu.com/s?wd=貼吧,那麼瀏覽器會自

Python 爬蟲從入門到路(四)

之前的文章我們做了一個簡單的例子爬取了百度首頁的 html,我們用到的是 urlopen 來開啟請求,它是一個特殊的opener(也就是模組幫我們構建好的)。但是基本的 urlopen() 方法不支援代理、cookie等其他的HTTP/HTTPS高階功能,所以我們需要用到 Python 的 opener 來自

Python 爬蟲從入門到路(五)

在之前的文章中我們帶入了 opener 方法,接下來我們看一下 opener 應用中的 ProxyHandler 處理器(代理設定)。 使用代理IP,這是爬蟲/反爬蟲的第二大招,通常也是最好用的。 很多網站會檢測某一段時間某個IP的訪問次數(通過流量統計,系統日誌等),如果訪問次數多的不像正常人,它會禁止

Python 爬蟲從入門到路(六)

在之前的文章中我們介紹了一下 opener 應用中的 ProxyHandler 處理器(代理設定),本篇文章我們再來看一下 opener 中的 Cookie 的使用。 Cookie 是指某些網站伺服器為了辨別使用者身份和進行Session跟蹤,而儲存在使用者瀏覽器上的文字檔案,Cookie可以保持登入資訊到

Python 爬蟲從入門到路(七)

在之前的文章中我們一直用到的庫是 urllib.request,該庫已經包含了平常我們使用的大多數功能,但是它的 API 使用起來讓人感覺不太好,而 Requests 自稱 “HTTP for Humans”,說明使用更簡潔方便。 Requests 唯一的一個非轉基因的 Pyth

Python 爬蟲從入門到路(八)

在之前的文章中我們介紹了一下 requests 模組,今天我們再來看一下 Python 爬蟲中的正則表達的使用和 re 模組。 實際上爬蟲一共就四個主要步驟: 明確目標 (要知道你準備在哪個範圍或者網站去搜索) 爬 (將所有的網站的內容全部爬下來) 取 (去掉對我們沒用處的資料) 處理資料(按照

Python 爬蟲從入門到路(九)

之前的文章我們介紹了一下 Python 中的正則表示式和與爬蟲正則相關的 re 模組,本章我們就利用正則表示式和 re 模組來做一個案例,爬取《糗事百科》的糗事並存儲到本地。 我們要爬取的網站連結是 https://www.qiushibaike.com/text/page/1/ 。

Python 爬蟲從入門到路(十一)

之前的文章我們介紹了一下 Xpath 模組,接下來我們就利用 Xpath 模組爬取《糗事百科》的糗事。 之前我們已經利用 re 模組爬取過一次糗百,我們只需要在其基礎上做一些修改就可以了,為了保證專案的完整性,我們重新再來一遍。 我們要爬取的網站連結是 https://www.qiushibai

Python 爬蟲從入門到路(十二)

之前的文章我們介紹了 re 模組和 lxml 模組來做爬蟲,本章我們再來看一個 bs4 模組來做爬蟲。 和 lxml 一樣,Beautiful Soup 也是一個HTML/XML的解析器,主要的功能也是如何解析和提取 HTML/XML 資料。 lxml 只會區域性遍歷,而Beautiful Soup

Python 爬蟲從入門到路(十三)

之前的文章我們介紹了一下 BeautifulSoup4 模組,接下來我們就利用 BeautifulSoup4 模組爬取《糗事百科》的糗事。 之前我們已經分別利用 re 模組和 Xpath 模組爬取過糗百,我們只需要在其基礎上做一些修改就可以了,為了保證專案的完整性,我們重新再來一遍。 我們要爬取

Python 爬蟲從入門到路(十四)

之前的文章我們已經可以根據 re 模組,Xpath 模組和 BeautifulSoup4 模組來爬取網站上我們想要的資料並且儲存在本地,但是我們並沒有對儲存資料的格式有要求,本章我們就來看資料的儲存格式 JSON 及 Python 中的 json 模組。 JSON(JavaScript Object Not

Python 爬蟲從入門到路(十五)

之前的文章我們介紹了一下 Python 的 json 模組,本章我們就介紹一下之前根據 Xpath 模組做的爬取《糗事百科》的糗事進行豐富和完善。 在 Xpath 模組的爬取糗百的案例中我們只是爬取了其中的糗事,然後儲存到本地,並沒有作者姓名,頭像等資訊,所有我們通過之前介紹的 path 模組講獲取到的完整