爬蟲技能——代碼模擬驗(yàn)證碼登錄網(wǎng)站之初級版

本人也是菜鳥一枚如有大佬看到就慢慢看我裝逼,若有新如坑的小伙伴我們一起加油。
在眾多的反爬手段中驗(yàn)證碼可以說是比較有效的手段之一了,今天寫了一個(gè)模擬登陸的程序與大家分享,也做為自己的一次總結(jié)。
要爬取的目標(biāo)網(wǎng)站:
https://so.gushiwen.org
先來說一下關(guān)于驗(yàn)證碼這塊的處理,慣用的有三種方法:
一是將驗(yàn)證碼下載到本地,然后手動在鍵盤上輸入。這種方法是最保險(xiǎn)的方法,但也是效率最低的方法,使用于爬蟲任務(wù)量不是很大,對爬蟲效率沒有較高的要求的情況。
二是采用tesseract庫,這種方法對一些簡單的圖形驗(yàn)證碼來說還是有用的,像純字母或純數(shù)字這種對圖片做一些簡單的處理即可,比如二值化、轉(zhuǎn)灰度等。是不是很方便?如果你覺得很方便的話,那你就錯(cuò)了!這種操作有6張驗(yàn)證碼能識別出3到4張就很牛逼了,但這還是達(dá)不到我們的要求怎么辦,那就機(jī)器學(xué)習(xí),今天不做深究。
三是用打碼平臺,這種方法呢,我會單獨(dú)的寫一篇詳細(xì)的用法。暫且不提。
思路:
1.向登陸頁面發(fā)送get請求,獲取到響應(yīng)內(nèi)容后拿自己用得最6的解析方式,將驗(yàn)證碼圖片的SRC取出來。
import requests
import urllib.request
from lxml import etree
s = requests.session()
url = 'https://so.gushiwen.org/user/login.aspx?'
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) '
'Chrome/70.0.3538.110 Safari/537.36'
}
r = requests.get(url=url,headers=headers)
tree = etree.HTML(r.text)
img_src = tree.xpath('//div[@class="mainreg2"][3]/img[@id="imgCode"]/@src')[0]
2.驗(yàn)證碼的完整地址是:https://so.gushiwen.org/RandCode.ashx,就是拼接嘛,然后向拼接完成的URL發(fā)送get請求下載驗(yàn)證碼圖片。
urllib.request.urlretrieve(image_src,'code.png')
3.抓包分析或者采用開發(fā)者工具找到登陸所需的參數(shù),這一步呢比較建議使用fiddler抓包工具,因?yàn)樵陂_發(fā)者工具中登陸所需的參數(shù)分布在不同的字段中,有時(shí)會找不齊(我就爬過這個(gè)坑),在fiddler中的請求詳情中的Webforms一欄中會包含所有登陸所需的參數(shù)和登陸的接口。
登陸的接口:https://so.gushiwen.org/user/login.aspx?from=http%3a%2f%2fso.gushiwen.org%2fuser%2fcollect.aspx
登陸所需的參數(shù):
'__VIEWSTATE':CsLDIp5JJGJCCuh76ipinjcqzhHVS2uRMHJ7JkXtVRllfxUzqBZuaRuwISfGf0aEGQCbecVIRKF76hW+VixVlqygRBZx9fAUn3foAXqf7YR2tuYNnDtLB/+dL8E=,
'__VIEWSTATEGENERATOR':C93BE1AE,
'from':'http://so.gushiwen.org/user/collect.aspx',
'email':'這個(gè)是賬號',
'pwd':'這個(gè)是密碼',
'code':code, #這個(gè)是驗(yàn)證碼
'denglu':'登陸',
4.向這個(gè)登陸接口發(fā)送post請求。
url = 'https://so.gushiwen.org/user/login.aspx?from=http%3a%2f%2fso.gushiwen.org%2fuser%2fcollect.aspx'
code = input('請輸入驗(yàn)證碼:')
formdata = { '__VIEWSTATE':CsLDIp5JJGJCCuh76ipinjcqzhHVS2uRMHJ7JkXtVRllfxUzqBZuaRuwISfGf0aEGQCbecVIRKF76hW+VixVlqygRBZx9fAUn3foAXqf7YR2tuYNnDtLB/+dL8E=,
'__VIEWSTATEGENERATOR':C93BE1AE,
'from':'http://so.gushiwen.org/user/collect.aspx',
'email':'erer4564654@163.com',
'pwd':'lakers24kebi',
'code':code,
'denglu':'登陸',
}
r = s.post(url=post_url,headers=headers,data=formdata)
print(r.text)
打印一下看響應(yīng)內(nèi)容,如果有修改密碼、賬號管理等內(nèi)容證明登陸成功。
然鵝。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
報(bào)錯(cuò)?。。。。。。。。。。。。。。。。。。。。。。。。。。。。。?!
是錯(cuò)在哪里呢?
發(fā)送請求、解析內(nèi)容、下載圖片又發(fā)送請求都沒錯(cuò)啊,咋會報(bào)錯(cuò)呢,這時(shí)我們就應(yīng)當(dāng)分析一下登陸接口所需的參數(shù)了,__VIEWSTATE和__VIEWSTATEGENERATOR這兩個(gè)參數(shù)都有各自的值他們會根據(jù)請求而隨機(jī)改變這個(gè)名詞叫表單令牌不能寫死,且他們能在源碼中找到,那就獲取他們在源碼中的路徑表達(dá)式來代替formdata中的參數(shù)值。
__VIEWSTATE =tree.xpath('//form[@name="aspnetForm"]/div[1]/input[@id="__VIEWSTATE"]/@value')[1]
__VIEWSTATEGENERATOR =tree.xpath('//form[@name="aspnetForm"]/div[2]/input[@id="__VIEWSTATEGENERATOR"]/@value')[1]
[0]這個(gè)的意思是,在xpath中路徑表達(dá)式獲取的是一個(gè)列表,而我要的是其中一個(gè)元素,xpath的索引是從1開始的(python中的索引和jsonpath從0開始的)。
再向登陸接口發(fā)一次請求,
post_url = 'https://so.gushiwen.org/user/login.aspx?from=http%3a%2f%2fso.gushiwen.org%2fuser%2fcollect.aspx'
code = input('請輸入驗(yàn)證碼:')
formdata = {
'__VIEWSTATE':__VIEWSTATE,
'__VIEWSTATEGENERATOR':__VIEWSTATEGENERATOR,
'from':'http://so.gushiwen.org/user/collect.aspx',
'email':'erer4564654@163.com',
'pwd':'lakers24kebi',
'code':code,
'denglu':'登陸',
}
r = s.post(url=post_url,headers=headers,data=formdata)
print(r.text)
這次應(yīng)該沒問題了吧,呵呵。
還是報(bào)錯(cuò)!
這次出錯(cuò)的原因是沒有維持同一會話,這個(gè)以后也會單獨(dú)寫一篇。
怎么解決呢?用s = requests.session()即可解決。那所有的請求就要采用這種方式了。
完整的源碼:
import requests
import urllib.request
from lxml import etree
s = requests.session()
url = 'https://so.gushiwen.org/user/login.aspx?'
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) '
'Chrome/70.0.3538.110 Safari/537.36'
}
發(fā)送get請求獲取驗(yàn)證碼的URL
r = s.get(url=url,headers=headers)
tree = etree.HTML(r.text)
img_src = tree.xpath('//div[@class="mainreg2"][3]/img[@id="imgCode"]/@src')[0]
拼接URL將驗(yàn)證碼下載到本地
image_src = 'https://so.gushiwen.org' + str(img_src)
r_image = s.get(url=image_src,headers=headers)
with open('code.png','wb') as fp:
fp.write(r_image.content)
解析獲得登陸所需的參數(shù)
__VIEWSTATE =tree.xpath('//form[@name="aspnetForm"]/div[1]/input[@id="__VIEWSTATE"]/@value')[0]
__VIEWSTATEGENERATOR =tree.xpath('//form[@name="aspnetForm"]/div[2]/input[@id="__VIEWSTATEGENERATOR"]/@value')[0]
登陸網(wǎng)站驗(yàn)證是否登陸成功
post_url = 'https://so.gushiwen.org/user/login.aspx?from=http%3a%2f%2fso.gushiwen.org%2fuser%2fcollect.aspx'
code = input('請輸入驗(yàn)證碼:')
formdata = {
'__VIEWSTATE':__VIEWSTATE,
'__VIEWSTATEGENERATOR':__VIEWSTATEGENERATOR,
'from':'http://so.gushiwen.org/user/collect.aspx',
'email':'erer4564654@163.com',
'pwd':'lakers24kebi',
'code':code,
'denglu':'登陸',
}
r = s.post(url=post_url,headers=headers,data=formdata)
print(r.text)
總結(jié):1.要以對話的形式發(fā)送每一次請求
2.先發(fā)get,再發(fā)get,最后發(fā)post
裝逼結(jié)束,我宣布退出裝逼界!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容