閒來無事,寫一個模擬登陸知乎的小demo。json
分析網頁發現:登陸須要的手機號,密碼,_xsrf參數,驗證碼dom
實現思路:scrapy
一、獲取驗證碼ide
二、獲取_xsrf 參數url
三、攜帶參數,請求登陸spa
驗證碼url : "https://www.zhihu.com/captcha.gif?r={t}&type=login&lang=en".format(t=t) # t 爲時間戳code
登陸界面url : "https://www.zhihu.com/#signin"orm
手機登陸申請url : 'https://www.zhihu.com/login/phone_num'blog
實現代碼:utf-8
首先配置文件 settings 中 ROBOTSTXT_OBEY = False
一、開頭及驗證碼處理部分,先重寫scrapy的start_requests方法。其次利用Pillow 來處理驗證碼,將驗證碼顯示出來,手動填寫(畢竟打碼是須要費用的),知乎默認的驗證碼爲中文,經分析發現驗證碼url 後面的 lang 參數決定語言,因此試着將語言改成英文(en)
# -*- coding: utf-8 -*- import scrapy import time import json from PIL import Image class ZhihuSpider(scrapy.Spider): name = 'zhihu' allowed_domains = ['www.zhihu.com'] # 重寫start_requests方法,處理驗證碼問題 def start_requests(self): t = str(time.time()).replace('','.') # 驗證碼url start_urls = "https://www.zhihu.com/captcha.gif?r={t}&type=login&lang=en".format(t=t) self.header ={ "User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36", 'Referer':' https: // www.zhihu.com /' } # 請求驗證碼的url return [scrapy.Request(url=start_urls,headers=self.header,callback=self.capcha,dont_filter=True)] # 獲取驗證碼 def capcha(self,response): # 獲取驗證碼,將驗證馬寫入本地 with open('capcha.jpg','wb') as f: f.write(response.body) try: # 利用pillow打開驗證碼 im = Image.open('capcha.jpg') im.show() except: print('請打開文件%s自行輸入'%("capcha.jpg")) cap = input("請輸入驗證碼>>") data = { "cap":cap } log_url = "https://www.zhihu.com/#signin" return scrapy.Request(url=log_url,callback=self.parse_login,headers=self.header,meta=data,dont_filter=True)
二、獲得驗證碼後,開始搞_xsrf參數,從登陸源碼中分析獲得_xsrf 在屬性爲name="_xsrf" 的input 節點中的value值
# 解析申請登錄的頁面,獲取參數xsrf def parse_login(self,response): xsrf = response.xpath('//input[@name="_xsrf"]/@value').extract_first() if not xsrf: print("請求錯誤") return '' phone_num = input("請輸入手機號碼") password = input("請輸入密碼") data = { 'captcha':response.meta['cap'], '_xsrf':xsrf, 'password':password, 'captcha_type':' en', 'phone_num':phone_num } # 用手機號-密碼 登陸的url url = 'https://www.zhihu.com/login/phone_num' return scrapy.FormRequest(url=url,callback=self.login_zh,headers=self.header,formdata=data,dont_filter=True,meta={'direct_list': [301, 302], 'direct_ignore': True})
三、參數都獲取到後就能夠模擬登陸了
# 驗證是否登陸成功 def login_zh(self,response): print(json.loads(response.text)['msg']) url = "https://www.zhihu.com/#signin" # 請求登陸知乎 yield scrapy.Request(url=url,callback=self.zh,headers=self.header,dont_filter=True,meta={'direct_list':[301,302],'direct_ignore':True}) # 後續解析知乎登陸後的頁面 def zh(self,response): print(response.text)
本次登陸後,並未對頁面進行解析,只是打印一下頁面,做爲驗證。