Scrapy 爬蟲模擬登錄的3種策略

1   Scrapy 爬蟲模擬登錄策略

前面學習了爬蟲的不少知識,都是分析 HTML、json 數據,有不少的網站爲了反爬蟲,除了須要高可用代理 IP 地址池外,還須要登陸,登陸的時候不單單須要輸入帳戶名和密碼,並且有可能驗證碼,下面就介紹 Scrapy 爬蟲模擬登錄的幾種策略。html

1.1  策略一:直接POST請求登陸

前面介紹的爬蟲 scrapy 的基本請求流程是 start_request 方法遍歷 start_urls 列表,而後 make_requests_from_url方法,裏面執行 Request 方法,請求 start_urls 裏面的地址,使用的是 GET 方法,因爲直接使用用戶名和密碼能夠登陸,使用 POST 方法進行登陸。git

例子:人人網登陸github

登陸地址:http://www.renren.com/PLogin.doshell

 

案例步驟:json

第一步:建立項目。瀏覽器

在 dos下切換到目錄安全

D:\scrapy_project服務器

 

新建一個新的爬蟲項目:scrapy startproject renrencookie

 

第二步:建立爬蟲。session

在 dos下切換到目錄。

D:\scrapy_project\renren\renren\spiders

用命令 scrapy genspider renren1 " renren.com" 建立爬蟲。

 

第三步: 經過瀏覽器登陸人人網,使用 fiddler 抓包抓取登陸 post 請求的 data。

第四步:編寫爬蟲文件。

import scrapy

# 登陸只須要提供 post 數據就能夠登陸的,就能夠用這種方法,

# 下面示例:post 數據是帳戶密碼

class Renren1Spider(scrapy.Spider):

    name = "renren1"

    allowed_domains = ["renren.com"]

 

    def start_requests(self):

        url = 'http://www.renren.com/PLogin.do'

        # FormRequest 是 Scrapy 發送 POST 請求的方法

        yield scrapy.FormRequest(

                url = url,

                formdata = {"email" : "13554799060", "password" : "xny123"},

                callback = self.parse_page)

    # 回調方法,對返回的 response 進行處理(把response.body保存到 xiao.html 中)

    def parse_page(self, response):

        with open("xiao.html", "wb") as filename:

            filename.write(response.body)

第五步:修改 settings 文件。

 

設置爬蟲請求的默認頭信息。

第六步:運行爬蟲。

在 dos下切換到目錄

D:\scrapy_project\renren\renren 下

經過命令運行爬蟲 :scrapy crawl renren1

 

第七步:查看結果。

 

xiao.html 中顯示的內容正是登陸本身人人網以後的主頁內容,說明登陸成功。

1.2  策略二:標準的模擬登錄

標準的模擬登陸方法:

一、首先發送登陸頁面的 get 請求,獲取到頁面裏的登陸必須的參數。

二、登陸必須的參數和帳戶密碼一塊兒 post 到服務器,登陸成功。

23.2.1 Cookie原理

HTTP 是無狀態的面向鏈接的協議, 爲了保持鏈接狀態, 標準的模擬登錄案例引入了 Cookie 機制。

Cookie 是 http 消息頭中的一種屬性,包括:

.Cookie 名字(Name)Cookie 的值(Value)

.Cookie 的過時時間(Expires/Max-Age)

.Cookie 做用路徑(Path)

.Cookie 所在域名(Domain),使用 Cookie 進行安全鏈接(Secure)。

前兩個參數是 Cookie 應用的必要條件,另外,還包括 Cookie 大小( Size,不一樣瀏覽器對Cookie 個數及大小限制是有差別的 )。

23.2.2 模擬登錄

爬取的網站:github (https://github.com/login)

案例步驟:

第一步:爬取前分析。

打開 fiddler,接着咱們打開 github 的登錄頁面(https://github.com/login ),輸入用戶名、密碼( 輸入錯誤的密碼 ),提交查看 fiddler 獲取的信息,結果入下:

 

輸入用戶名和錯誤密碼獲取的 fiddler 結果:

 

咱們用 google 瀏覽器看源碼也能夠看到 form 提交時會加入 authenticity_token 參數一塊兒,以下圖:

 

第二步:建立項目。

在 dos下切換到目錄

D:\scrapy_project

 

新建一個新的爬蟲項目:scrapy startproject github

 

第三步:建立爬蟲。

在 dos下切換到目錄。

D:\scrapy_project\github\github\spiders

用命令 scrapy genspider gh "github.com" 建立爬蟲。

 

第四步: 開始前的準備工做。

(一)、在 scrapy.cfg 同級目錄下建立 pycharm 調試腳本 run.py,內容以下:

# -*- coding: utf-8 -*-

from scrapy import cmdline

cmdline.execute("scrapy crawl github".split())

 

(二)修改 settings 中的 ROBOTSTXT_OBEY = True 參數爲 False,由於默認爲 True,就是要遵照 robots.txt 的規則, robots.txt 是遵循 Robot協議 的一個文件,它保存在網站的服務器中,它的做用是,告訴搜索引擎爬蟲,本網站哪些目錄下的網頁不但願你進行爬取收錄。在 Scrapy 啓動後,會在第一時間訪問網站的 robots.txt 文件,而後決定該網站的爬取範圍。查看 robots.txt 能夠直接網址後接 robots.txt 便可。

例如百度:https://www.baidu.com/robots.txt

 

修改 settings 文件。

(三)模擬登錄時,必須保證 settings.py 裏的 COOKIES_ENABLED (Cookies中間件) 處於開啓狀態。

COOKIES_ENABLED = True

 

第五步:編寫爬蟲文件-獲取 authenticity_token。

首先要打開登錄頁面,獲取 authenticity_token,代碼以下:

import scrapy

 

class GithubSpider(scrapy.Spider):

    name = 'gh'

    allowed_domains = ['github.com']

 

    def start_requests(self):

        urls = ['https://github.com/login']

        for url in urls:

            # 重寫 start_requests 方法,經過 meta 傳入特殊 key cookiejar,爬取 url 做爲參數傳給回調函數

            yield scrapy.Request(url, meta={'cookiejar': 1}, callback=self.github_login)

 

    def github_login(self, response):

        # 首先獲取authenticity_token,這裏能夠藉助scrapy shell 」url「來獲取頁面

        # 而後從源碼中獲取到authenticity_token的值

        authenticity_token = response.xpath("//input[@name='authenticity_token']/@value").extract_first()

        # 利用 scrapy 內置 logger 打印 info 信息

        self.logger.info('authenticity_token='+ authenticity_token)

        pass

運行結果:

 

經過運行的結果,能夠看到咱們已經獲取了 authenticity_token 的值,這一步重點要說明meta、cookiejar 和 logger。

【meta】:字典格式的元數據,能夠傳遞給下一個函數 meta。

【cookiejar】:是 meta 的一個特殊的key,經過 cookiejar 參數能夠支持多個會話對某網站進行爬取,能夠對 cookie 作標記,1,2,3,4......這樣 scrapy 就維持了多個會話;

【logger】:scrapy 爲每一個 spider 實例內置的日誌記錄器。

爲了能使用同一個狀態持續的爬取網站, 就須要保存cookie, 使用cookie保存狀態, Scrapy 提供了 cookie 處理的中間件, 能夠直接拿來使用,Scrapy 官方的文檔中給出了下面的代碼範例 :

for i, url in enumerate(urls):

    yield scrapy.Request("http://www.example.com", meta={'cookiejar': i},

        callback=self.parse_page)

def parse_page(self, response):

    # do some processing

    return scrapy.Request("http://www.example.com/otherpage",

        meta={'cookiejar': response.meta['cookiejar']},

        callback=self.parse_other_page)

第六步:修改爬蟲文件- FormRequest(登陸表單提交)

Scrapy 提供了 FormRequest 類,是 Request 類的擴展,專門用來進行 Form 表單提交。咱們主要使用 FormRequest.from_response()方法來模擬簡單登錄,經過FormRequest.from_response 提交後,交給回調函數處理。代碼以下:

import scrapy

 

class GithubSpider(scrapy.Spider):

    name = 'gh'

    allowed_domains = ['github.com']

 

    def start_requests(self):

        urls = ['https://github.com/login']

        for url in urls:

            # 重寫 start_requests 方法,經過 meta 傳入特殊 key cookiejar,爬取 url 做爲參數傳給回調函數

            yield scrapy.Request(url, meta={'cookiejar': 1}, callback=self.github_login)

 

    def github_login(self, response):

        # 首先獲取authenticity_token,這裏能夠藉助scrapy shell 」url「來獲取頁面

        # 而後從源碼中獲取到authenticity_token的值

        authenticity_token = response.xpath("//input[@name='authenticity_token']/@value").extract_first()

        # 利用 scrapy 內置 logger 打印 info 信息

        self.logger.info('authenticity_token='+ authenticity_token)

        # url 能夠從 fiddler 抓取中獲取,dont_click 做用是若是是 True,表單數據將被提交,而不須要單擊任何元素。

        return scrapy.FormRequest.from_response(

        response,

        url='https://github.com/session',

        meta = {'cookiejar': response.meta['cookiejar']},

        headers = self.headers,

        formdata = {'utf8':'?',

        'authenticity_token': authenticity_token,

        'login': 'xxxxxx@qq.com',

        'password': 'xxxxxx'},

        callback = self.github_after,

        dont_click = True,

        )

第七步:修改爬蟲文件- 假裝頭部。

爲了更真實的模擬瀏覽器登錄網站,須要進行頭部假裝, 在 scrapy 中 Request 和 FormRequest 初始化的時候都有一個 headers 字段, 能夠自定義頭部, 這樣咱們能夠添加 headers 字段。

# 頭信息直接從 fiddler 中複製出來

headers = {

    "Connection": "keep-alive",

    "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.111 Safari/537.36",

    "Referer": "https: // github.com /",

    "Content - Type": "application / x - www - form - urlencoded",

}

第八步:修改爬蟲文件- 增長回調函數,主要是登錄成功以後,獲取登陸以後返回的頁面(response)的元素進行斷言,驗證登陸結果。

登陸以後,主頁以下:

 

# 回調函數

def github_after(self, response):

    # 獲取登陸頁面主頁中的字符串'Browse activity'

    list = response.xpath("//a[@class=‘tabnav-tab selected‘]/text()").extract()

    # 若是含有字符串,則打印日誌說明登陸成功

    if 'Browse activity' in list:

        self.logger.info('我已經登陸成功了,這是我獲取的關鍵字:Browse activity')

    else:

        self.logger.error('登陸失敗')

第九步:整理完整的爬蟲文件

import scrapy

 

class GithubSpider(scrapy.Spider):

    name = 'gh'

    allowed_domains = ['github.com']

    # 頭信息直接從 fiddler 中複製出來

    headers = {

    "Connection": "keep-alive",

    "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.111 Safari/537.36",

    "Referer": "https: // github.com /",

    "Content - Type": "application / x - www - form - urlencoded",

    }

 

    def start_requests(self):

        urls = ['https://github.com/login']

        for url in urls:

            # 重寫 start_requests 方法,經過 meta 傳入特殊 key cookiejar,爬取 url 做爲參數傳給回調函數

            yield scrapy.Request(url, meta={'cookiejar': 1}, callback=self.github_login)

 

    def github_login(self, response):

        # 首先獲取authenticity_token,這裏能夠藉助scrapy shell 」url「來獲取頁面

        # 而後從源碼中獲取到authenticity_token的值

        authenticity_token = response.xpath("//input[@name='authenticity_token']/@value").extract_first()

        # 利用 scrapy 內置 logger 打印 info 信息

        self.logger.info('authenticity_token='+ authenticity_token)

        # url 能夠從 fiddler 抓取中獲取,dont_click 做用是若是是 True,表單數據將被提交,而不須要單擊任何元素。

        return scrapy.FormRequest.from_response(

        response,

        url='https://github.com/session',

        meta = {'cookiejar': response.meta['cookiejar']},

        headers = self.headers,

        formdata = {'utf8':'?',

        'authenticity_token': authenticity_token,

        'login': '55666727@qq.com',

        'password': 'xny8816056'},

        callback = self.github_after,

        dont_click = True,

        )

 

    # 回調函數

    def github_after(self, response):

        # 獲取登陸頁面主頁中的字符串'Browse activity'

        list = response.xpath("//a[@class=‘tabnav-tab selected‘]/text()").extract()

        # 若是含有字符串,則打印日誌說明登陸成功

        if 'Browse activity' in list:

            self.logger.info('我已經登陸成功了,這是我獲取的關鍵字:Browse activity')

        else:

            self.logger.error('登陸失敗')

第十步:查看運行的結果。

 

經過運行的結果說明登陸成功。

1.3  策略三:直接使用保存登錄狀態的 Cookie 模擬登錄

若是實在沒辦法了,能夠用策略三這種方法模擬登陸,雖然麻煩一點,可是成功率100%。

案例步驟:

第一步:建立項目。

在 dos下切換到目錄

D:\scrapy_project

新建一個新的爬蟲項目:scrapy startproject renren2

 

第二步:建立爬蟲。

在 dos下切換到目錄。

D:\scrapy_project\renren2\renren2\spiders

用命令 scrapy genspider ren2 "renren.com" 建立爬蟲。

 

第三步: 經過瀏覽器登陸人人網,使用 fiddler 抓包抓取登陸後的Cookis。

 

第四步: 開始前的準備工做。

(一)、在 scrapy.cfg 同級目錄下建立 pycharm 調試腳本 run.py,內容以下:

# -*- coding: utf-8 -*-

from scrapy import cmdline

cmdline.execute("scrapy crawl renren".split())

 

(二)修改 settings 中的 ROBOTSTXT_OBEY = True 參數爲 False,由於默認爲 True,就是要遵照 robots.txt 的規則, robots.txt 是遵循 Robot協議 的一個文件,它保存在網站的服務器中,它的做用是,告訴搜索引擎爬蟲,本網站哪些目錄下的網頁不但願你進行爬取收錄。在 Scrapy 啓動後,會在第一時間訪問網站的 robots.txt 文件,而後決定該網站的爬取範圍。查看 robots.txt 能夠直接網址後接 robots.txt 便可。

修改 settings 文件。

(三)模擬登錄時,必須保證 settings.py 裏的 COOKIES_ENABLED ( Cookies 中間件) 處於開啓狀態。

COOKIES_ENABLED = True

 

第五步: 編寫爬蟲文件。

import scrapy

 

class RenrenSpider(scrapy.Spider):

    name = "renren"

    allowed_domains = ["renren.com"]

    Cookies = {

        "anonymid": "jlvxr345k9ondn",

        "wp_fold": "0",

        "depovince": "GW",

        "jebecookies": "3af719cc-f819-4493-bcb6-c967fc59f04a|||||",

        "_r01_": "1",

        "JSESSIONID": "abcwnUubDsWO467i0mgxw",

        "ick_login":"27af5597-30d7-469c-b7c4-184a6e335fcb",

        "jebe_key":"d1f5682d-03b4-46cd-87c0-dc297525ed11%7Ccfcd208495d565ef66e7dff9f98764da%7C1536628574466%7C0%7C1536628572944",}

 

 

    # 能夠重寫 Spider 類的 start_requests 方法,附帶 Cookie 值,發送 POST 請求

    def start_requests(self):

        url = 'http://www.renren.com/PLogin.do'

        # FormRequest 是 Scrapy 發送 POST 請求的方法

        yield scrapy.FormRequest(url, cookies = self.Cookies, callback = self.parse_page)

 

    # 處理響應內容

    def parse_page(self, response):

        print("===========" + response.url)

        with open("xiao2.html", "wb") as filename:

            filename.write(response.body)

第六步: 運行程序,查看運行結果。

 

Xiao2.html 中顯示的內容正是登陸本身人人網以後的主頁內容,說明登陸成功。

相關文章
相關標籤/搜索