前面學習了爬蟲的不少知識,都是分析 HTML、json 數據,有不少的網站爲了反爬蟲,除了須要高可用代理 IP 地址池外,還須要登陸,登陸的時候不單單須要輸入帳戶名和密碼,並且有可能驗證碼,下面就介紹 Scrapy 爬蟲模擬登錄的幾種策略。html
前面介紹的爬蟲 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 中顯示的內容正是登陸本身人人網以後的主頁內容,說明登陸成功。
標準的模擬登陸方法:
一、首先發送登陸頁面的 get 請求,獲取到頁面裏的登陸必須的參數。
二、登陸必須的參數和帳戶密碼一塊兒 post 到服務器,登陸成功。
HTTP 是無狀態的面向鏈接的協議, 爲了保持鏈接狀態, 標準的模擬登錄案例引入了 Cookie 機制。
Cookie 是 http 消息頭中的一種屬性,包括:
.Cookie 名字(Name)Cookie 的值(Value)
.Cookie 的過時時間(Expires/Max-Age)
.Cookie 做用路徑(Path)
.Cookie 所在域名(Domain),使用 Cookie 進行安全鏈接(Secure)。
前兩個參數是 Cookie 應用的必要條件,另外,還包括 Cookie 大小( Size,不一樣瀏覽器對Cookie 個數及大小限制是有差別的 )。
爬取的網站: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('登陸失敗')
第十步:查看運行的結果。
經過運行的結果說明登陸成功。
若是實在沒辦法了,能夠用策略三這種方法模擬登陸,雖然麻煩一點,可是成功率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 中顯示的內容正是登陸本身人人網以後的主頁內容,說明登陸成功。