在使用selenium訪問網(wǎng)站概漱,爬取相應(yīng)內(nèi)容時(shí),經(jīng)常需要模擬登陸,現(xiàn)在基本每個(gè)網(wǎng)站登陸都具有驗(yàn)證碼了拔妥,雖然驗(yàn)證碼識別可以利用第三方來完成,但是我們還是需要先獲取驗(yàn)證碼的圖片才可以借助第三方來識別达箍,而在selenium如果你先訪問獲取驗(yàn)證碼后在進(jìn)行二次訪問驗(yàn)證没龙,驗(yàn)證碼是會刷新的,所以我們需要獲取實(shí)時(shí)的驗(yàn)證碼缎玫。下面是獲取識別驗(yàn)證碼的兩種方法硬纤。
一、利用urllib庫來直接獲取驗(yàn)證碼
首先需要安裝urllib庫赃磨,然后利用selenium訪問相應(yīng)網(wǎng)站筝家,對網(wǎng)站進(jìn)行解析,獲取驗(yàn)證碼的url訪問連接邻辉,利用urllib庫通過剛剛的url來獲取圖片的二進(jìn)制數(shù)據(jù)并進(jìn)行儲存溪王。
page_img = urllib.request.urlopen(img_src).read()
這樣就獲取了圖片的二進(jìn)制數(shù)據(jù)了,這是較為簡單的值骇,注意利用這個(gè)方法的時(shí)候還需要導(dǎo)入requests庫莹菱,不然會報(bào)錯(cuò)。
下面是我利用該方法獲取12306網(wǎng)站的驗(yàn)證碼例子的代碼:
from selenium import webdriver
from lxml import etree
import requests
import urllib
from time import sleep
#指定Chrome瀏覽器位置
option = webdriver.ChromeOptions()
option.binary_location = 'E:\\Google Chrome瀏覽器\\Google\\Chrome\\Application\\chrome.exe'
#進(jìn)行偽裝
option.add_experimental_option('excludeSwitches',['enable-automation'])
#生成瀏覽器對象
bro = webdriver.Chrome(executable_path=r'E:\chrome瀏覽器驅(qū)動程序\chromedriver_win32\chromedriver',options=option)
bro.get('https://kyfw.12306.cn/otn/resources/login.html')
sleep(1)
#定位到賬號密碼登錄標(biāo)簽
a_tag = bro.find_element_by_xpath('/html/body/div[2]/div[2]/ul/li[2]/a')
#點(diǎn)擊切換為賬號密碼登錄才有驗(yàn)證碼
a_tag.click()
sleep(1)
#獲取頁面源碼
page_text = bro.page_source
#生成etree對象
tree = etree.HTML(page_text)
#獲取驗(yàn)證碼的下載地址
img_src = tree.xpath('//*[@id="J-loginImg"]/@src')[0]
#利用圖片地址獲取圖片二級制數(shù)據(jù)
page_img = urllib.request.urlopen(img_src).read()
#將獲取的二級制數(shù)據(jù)進(jìn)行持久化存儲
with open('img.jpg','wb') as fp:
fp.write(page_img)
二雷客、利用selenium庫截圖獲取驗(yàn)證碼
該方法比第一種麻煩一點(diǎn)芒珠,首先還是利用selenium訪問網(wǎng)站,注意這樣要設(shè)置瀏覽器窗口最大化搅裙,不然會出現(xiàn)偏差皱卓。
#設(shè)置瀏覽器全屏化
bro.maximize_window()
然后進(jìn)行全局截圖,利用頁面解析定位到驗(yàn)證碼的標(biāo)簽處部逮,調(diào)用location方法獲取驗(yàn)證碼的左上角坐標(biāo)娜汁,再調(diào)用size方法獲取驗(yàn)證碼的寬度和高度,最后得到右下角坐標(biāo)兄朋。然后利用PIL庫中的Image類來打開剛剛截取的全局圖片掐禁,根據(jù)獲取的左上角坐標(biāo)和右下角坐標(biāo)對截圖進(jìn)行裁剪從而獲取驗(yàn)證碼圖片。
location = code_png_lel.location
print('location',location)
#獲取驗(yàn)證碼的長寬
size = code_png_lel.size
print('size',size)
#location獲取是根據(jù)百分之百縮放的颅和,而我電腦的縮放是百分之125所以出現(xiàn)偏差
#圖片左上角和右下角的xy坐標(biāo)
rangle = (
int(location['x']), int(location['y']), int(location['x']+size['width']), int(location['y']+size['height'])
)
print('rangle',rangle)
#對全局頁面進(jìn)行截圖獲取局部驗(yàn)證碼
i = Image.open('./aa.png')
#按照給定xy坐標(biāo)裁剪
frame = i.crop(rangle)
但是我這樣截圖還是出現(xiàn)偏差了傅事,在網(wǎng)上一查才發(fā)現(xiàn)location方法獲取的坐標(biāo)是按顯示100%時(shí)得到的,而截圖所使用的坐標(biāo)卻是需要根據(jù)顯示縮放比例縮放后對應(yīng)的圖片所確定的峡扩,因此就出現(xiàn)了偏差蹭越。
這就與計(jì)算機(jī)的縮放顯示有關(guān)了,windows可以在桌面右鍵-->顯示設(shè)置-->縮放與布局教届。
若是百分之100就不會有偏差响鹃,我的是百分之125所以有偏差。
1案训、將其調(diào)整為100%會運(yùn)行就不會報(bào)錯(cuò)了买置。但是100%看著不舒服所以我用了第二種方法。
2强霎、將裁剪的坐標(biāo)全部乘以縮放的比例忿项,即左上角和右下角的x,y軸坐標(biāo)全部乘以1.25.
location = code_png_lel.location
print('location',location)
#獲取驗(yàn)證碼的長寬
size = code_png_lel.size
print('size',size)
#location獲取是根據(jù)百分之百縮放的,而我電腦的縮放是百分之125所以出現(xiàn)偏差
k=1.25
#圖片左上角和右下角的xy坐標(biāo)
rangle = (
int(location['x'])*k, int(location['y'])*k, int(location['x']+size['width'])*k, int(location['y']+size['height'])*k
)
print('rangle',rangle)
#對全局頁面進(jìn)行截圖獲取局部驗(yàn)證碼
i = Image.open('./aa.png')
#按照給定xy坐標(biāo)裁剪
frame = i.crop(rangle)
下面是我利用該方法獲取12306的驗(yàn)證碼:
from selenium import webdriver
from lxml import etree
from PIL import Image
from time import sleep
#給定Chrome瀏覽器的位置和進(jìn)行偽裝
option = webdriver.ChromeOptions()
option.binary_location = 'E:\\Google Chrome瀏覽器\\Google\\Chrome\\Application\\chrome.exe'
option.add_experimental_option('excludeSwitches',['enable-automation'])
#生成瀏覽器對象
bro = webdriver.Chrome(executable_path=r'E:\chrome瀏覽器驅(qū)動程序\chromedriver_win32\chromedriver',options=option)
#設(shè)置瀏覽器全屏
bro.maximize_window()
bro.get('https://kyfw.12306.cn/otn/resources/login.html')
sleep(1)
#定位到賬號密碼的位置
a_tag = bro.find_element_by_xpath('/html/body/div[2]/div[2]/ul/li[2]/a')
#點(diǎn)擊賬號密碼登錄
a_tag.click()
sleep(2)
#利用save_screenshot()將當(dāng)前頁面解析截圖并保留
bro.save_screenshot('aa.png')
#定位到驗(yàn)證碼的標(biāo)簽所在
sleep(0.4)
code_png_lel = bro.find_element_by_id('J-loginImg')
#獲取驗(yàn)證碼的左上角坐標(biāo)x,y
sleep(0.4)
location = code_png_lel.location
print('location',location)
#獲取驗(yàn)證碼的長寬
size = code_png_lel.size
print('size',size)
#location獲取是根據(jù)百分之百縮放的城舞,而我電腦的縮放是百分之125所以出現(xiàn)偏差
k=1.25
#圖片左上角和右下角的xy坐標(biāo)
rangle = (
int(location['x'])*k, int(location['y'])*k, int(location['x']+size['width'])*k, int(location['y']+size['height'])*k
)
print('rangle',rangle)
#對全局頁面進(jìn)行截圖獲取局部驗(yàn)證碼
i = Image.open('./aa.png')
#按照給定xy坐標(biāo)裁剪
frame = i.crop(rangle)
frame.save('./code.png')
設(shè)置睡眠時(shí)間是因?yàn)榕戮W(wǎng)站還沒將驗(yàn)證碼顯示出來便截圖了轩触。