1. 程式人生 > >Scrapy 爬蟲模擬登陸的3種策略

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

除了 size 是我 settings extra art 代碼 erro 自定義

1 Scrapy 爬蟲模擬登陸策略

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

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

前面介紹的爬蟲 scrapy 的基本請求流程是 start_request 方法遍歷 start_urls 列表,然後 make_requests_from_url方法,裏面執行 Request 方法,請求 start_urls 裏面的地址,使用的是 GET 方法,由於直接使用用戶名和密碼可以登錄,使用 POST 方法進行登錄。

例子:人人網登錄

登錄地址:http://www.renren.com/PLogin.do

技術分享圖片

案例步驟:

第一步:創建項目。

在 dos下切換到目錄

D:\scrapy_project

技術分享圖片

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

技術分享圖片

技術分享圖片

第二步:創建爬蟲。

在 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 策略二:標準的模擬登陸

標準的模擬登錄方法:

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

2、登錄必須的參數和賬戶密碼一起 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‘: ‘[email protected]‘,

‘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‘: ‘[email protected]‘,

‘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 中顯示的內容正是登錄自己人人網之後的主頁內容,說明登錄成功。

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