滑塊驗證碼登錄
簡介
現(xiàn)在很多網(wǎng)站的登錄,都采用了拖動圖片滑塊的驗證碼方式來進行驗證登錄,比如嗶哩嗶哩和京東等。在使用爬蟲等自動化程序時,如何通過滑塊驗證,就成了需要解決的問題。
這里通過大名鼎鼎的ddddocr圖片識別庫,和模擬瀏覽器操作的selenium庫來實現(xiàn)
Selenium簡介
安裝瀏覽器driver
首先你需要下載一個瀏覽器的driver,Chrome的下載地址如下,注意參考你的Chrome版本,下載對應(yīng)的exe文件,然后運行即可。
下載地址:Chrome for Testing availability (googlechromelabs.github.io)
運行后出現(xiàn)下圖,放著就行了:
pip安裝Selenium包
pip install selenium
Selenium的基本使用如下:該例子打開百度首頁,并搜索python
from selenium import webdriver
from selenium.webdriver.common.by import By
browser = webdriver.Chrome()
browser.get('https://www.baidu.com/')
# 通過元素ID獲取元素
kw_input = browser.find_element(By.ID, 'kw')
# 模擬用戶輸入行為
kw_input.send_keys('Python')
# 通過CSS選擇器獲取元素
su_button = browser.find_element(By.CSS_SELECTOR, '#su')
# 模擬用戶點擊行為
su_button.click()
input("請輸入回車結(jié)束")
ddddocr簡介
ddddorc庫是一個比較好用的圖片識別庫,目前支持滑塊、文字驗證碼、點選驗證碼的識別
官方地址:https://github.com/sml2h3/ddddocr
我們用到的語法如下(事實上該例子就在官方文檔首頁:
slide = ddddocr.DdddOcr(det=False, ocr=False)
# 這是滑塊圖片
with open('target.jpg', 'rb') as f:
target_bytes = f.read()
# 這是背景大圖片
with open('background.jpg', 'rb') as f:
background_bytes = f.read()
# 返回的是坐標關(guān)系
res = slide.slide_match(target_bytes, background_bytes, simple_target=True)
print(res)
返回值如下,四個值分別表示左上角和右下角的,水平和垂直距離:
{'target_y': 0, 'target': [113, 61, 163, 111]}
實戰(zhàn)舉例
本次我們來模擬登錄京東,因為剛好是一個很容易獲取到的滑塊驗證碼網(wǎng)站~
用Selenium獲取對應(yīng)元素進行登錄
我們分別獲取用戶名和密碼框,輸入賬號和密碼,然后獲取登錄框點擊登錄
def sel_main():
browser = webdriver.Chrome()
# browser.maximize_window()
browser.get('https://passport.jd.com/uc/login')
# 點擊賬戶密碼登錄
up_btn = browser.find_element(By.ID, 'pwd-login')
up_btn.click()
# 通過元素ID獲取用戶名和密碼框
username_input = browser.find_element(By.ID, 'loginname')
pw_input = browser.find_element(By.ID, 'nloginpwd')
# 模擬輸入
username_input.send_keys('1xxxxxx93')
pw_input.send_keys('111222333')
# 選取登錄按鈕
submit_btn = browser.find_element(By.ID, 'loginsubmit')
# su_button = browser.find_element(By.CSS_SELECTOR, '#su')
# 模擬用戶點擊行為
submit_btn.click()
此時會跳出滑塊驗證碼的圖片,我們分別獲取他們,將圖片下載到本地:
# 獲取驗證碼圖片背景大圖
captcha = browser.find_element(By.XPATH, '//div[@class="JDJRV-bigimg"]/img')
captcha_img = captcha.get_attribute('src')
captcha_size = (captcha.size['width'], captcha.size['height'])
handle_img(captcha_img, 'bg', captcha_size, 'bg_sized')
# 獲取滑塊小圖
wrap = browser.find_element(By.XPATH, '//div[@class="JDJRV-smallimg"]/img')
wrap_img = wrap.get_attribute('src')
wrap_size = (wrap.size['width'], wrap.size['height'])
handle_img(wrap_img, 'sm', wrap_size, 'sm_sized')
對驗證碼圖片進行處理
下載到的圖片是圖片的原始大小,這就會產(chǎn)生一個問題。在瀏覽器中進行拖動時,實際要拖動的是圖片在瀏覽器中實際渲染出來的大小。這兩者中間是存在誤差的,所以通過以下方法對圖片進行處理,讓它變成和瀏覽器中是一樣大的:
def handle_img(img_src: str, name: str, size: tuple, name_sized: str):
"""
對下載的驗證碼圖片進行處理
:param img_src: 原圖片編碼
:param name: 保存名稱
:param size: 調(diào)整的大小,元組(width, height)
:param name_sized: 調(diào)整后的圖片名
:return: 無
"""
s_img = img_src.replace('data:image/png;base64,', '')
img_byte = base64.b64decode(s_img)
with open(f"../images/{name}.png", "wb") as f:
f.write(img_byte)
img = Image.open(f"../images/{name}.png")
res_img = img.resize(size)
res_img.save(f"../images/{name_sized}.png")
計算拖動距離
驗證碼圖片和滑塊都獲取到了,通過以下方法,來計算拖動距離
def get_distance(tg_img, bg_img):
"""
獲取滑動距離
:param bg_img: 底層大圖片
:param tg_img: 滑塊小圖片
:return: 返回距離
"""
# 讀取圖片
with open(f"../images/{tg_img}.png", "rb") as f:
tg = f.read()
with open(f"../images/{bg_img}.png", "rb") as f:
bg = f.read()
det = ddddocr.DdddOcr(det=False, ocr=False, show_ad=False)
# 目標圖無多余背景,需要加入simple_target參數(shù)
res = det.slide_match(tg, bg, simple_target=True)
return res['target'][0]
模擬進行拖動
滑塊的拖動顯然不能直接拖過去,那樣速度太快太準確,一下子就被發(fā)現(xiàn)不是人類啦。所以我們只能盡可能模擬手動操作,用以下方法進行拖動:
def do_moves(browser, distance, btn):
"""
加速度滑動法,計算生成軌跡然后滑動
:param browser: 瀏覽器對象
:param distance: 滑動距離
:param btn: 滑動對象
:return:無
"""
# 生成運動軌跡
track = []
current = 0
mid = distance * 4 / 5
t = 0.2
v = 1
while current < distance:
if current < mid:
a = 4
else:
a = -3
v0 = v
v = v0 + a*t
move = v0*t + 0.5*a*t*t
current += move
track.append(round(move))
ActionChains(browser).click_and_hold(btn).perform()
for x in track:
ActionChains(browser).move_by_offset(xoffset=x, yoffset=random.randint(-5, 5)).perform()
# 重置滑動值,否則多次滑動會超出范圍
ActionChains(browser).reset_actions()
time.sleep(0.5)
ActionChains(browser).release(on_element=btn).perform()
拖動不一定成功,所以用一個try的循環(huán),如果失敗就再來一次
保存cookie
登錄成功后用如下語句保存cookie
cookies = browser.get_cookies()
with open("cookies.json", "w") as c:
c.write(f"{cookies}")
使用cookie
既然已經(jīng)模擬登錄成功了,那么要如何使用cookie呢?
以下例子訪問一個需要登錄的頁面,來使用cookie
def use_cookies():
# 我的訂單頁面,需要登錄才能訪問
test_url = "https://order.jd.com/center/list.action"
# 從本地讀取cookie文件,
with open("cookies.json", 'r') as c:
cookies = eval(c.read())
cookie = [item["name"] + "=" + item["value"] for item in cookies]
# 拼接成字符串
cookie_str = '; '.join(item for item in cookie)
print(cookie_str)
# 將cookie放入header中
header = {
'cookie': cookie_str,
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'
}
html = requests.get(test_url, headers=header)
print(html.text)
完整代碼請參考如下鏈接:
https://github.com/h-kayotin/kayotin_toolbox/blob/master/sel/sel_JD_login.py文章來源:http://www.zghlxwxcb.cn/news/detail-815072.html
參考資料:https://github.com/zjy6622/python-/blob/master/selenium京東模擬登陸.py文章來源地址http://www.zghlxwxcb.cn/news/detail-815072.html
到了這里,關(guān)于用Selenium實現(xiàn)滑塊驗證碼登錄的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!