Scrapy 爬蟲模擬登陸的3種策略
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種策略