流程分析:
- 使用selenium打開登錄頁面
- 對當前selenium打開的這張頁面進行截圖
- 對當前圖片的局部區域(驗證碼圖片區域)進行截圖
- 這樣驗證碼圖片和模擬登錄進行所顯示的圖片一一對應(如果我們對圖片發起請求每次請求都不一樣無法准確定位及點擊)
- 使用超級鷹識別驗證碼圖片(坐標)
對當前selenium打開的這張頁面進行截圖
# -*- coding: utf-8 -*-
from selenium import webdriver
import time
from PIL import Image
from Chaojiying_Python import chaojiying
from selenium.webdriver import ActionChains
bro = webdriver.Chrome()
url = "https://kyfw.12306.cn/otn/resources/login.html"
bro.get(url)
bro.implicitly_wait(5) #靜默等待最大5秒,保證頁面加載完畢
time.sleep(1)
bro.find_element_by_xpath("/html/body/div[2]/div[2]/ul/li[2]/a").click()
bro.save_screenshot('aa.png')# save_screenshot 將當前頁面進行截圖保存
# 確定驗證碼圖片對應的左上角和右下角坐標(裁剪的區域就確定了)
code_img_ele = bro.find_element_by_xpath('//*[@id="J-loginImg"]')
location = code_img_ele.location # 驗證碼圖片左上角的坐標 x,y
print("location:",location)
size = code_img_ele.size # 驗證碼標簽對應的長和寬
print("size",size)
定位驗證碼圖片左上角及右下角得坐標
# -*- coding: utf-8 -*-
from selenium import webdriver
import time
from PIL import Image
from Chaojiying_Python import chaojiying
from selenium.webdriver import ActionChains
bro = webdriver.Chrome()
url = "https://kyfw.12306.cn/otn/resources/login.html"
bro.get(url)
bro.implicitly_wait(5) #靜默等待最大5秒,保證頁面加載完畢
time.sleep(1)
bro.find_element_by_xpath("/html/body/div[2]/div[2]/ul/li[2]/a").click()
bro.save_screenshot('aa.png')# save_screenshot 將當前頁面進行截圖保存
# 確定驗證碼圖片對應的左上角和右下角坐標(裁剪的區域就確定了)
code_img_ele = bro.find_element_by_xpath('//*[@id="J-loginImg"]')
location = code_img_ele.location # 驗證碼圖片左上角的坐標 x,y
print("location:",location)
size = code_img_ele.size # 驗證碼標簽對應的長和寬
print("size",size)
# # 左下角和右下角坐標
rangle = (int(location["x"]),int(location["y"]),int(location["x"] + size["width"]),int(location["y"] + size["height"]))
print(rangle)
根據坐標區域進行裁剪
# -*- coding: utf-8 -*-
from selenium import webdriver
import time
from PIL import Image
from Chaojiying_Python import chaojiying
from selenium.webdriver import ActionChains
bro = webdriver.Chrome()
url = "https://kyfw.12306.cn/otn/resources/login.html"
bro.get(url)
bro.implicitly_wait(5) #靜默等待最大5秒,保證頁面加載完畢
time.sleep(1)
bro.find_element_by_xpath("/html/body/div[2]/div[2]/ul/li[2]/a").click()
bro.save_screenshot('aa.png')# save_screenshot 將當前頁面進行截圖保存
# 確定驗證碼圖片對應的左上角和右下角坐標(裁剪的區域就確定了)
code_img_ele = bro.find_element_by_xpath('//*[@id="J-loginImg"]')
location = code_img_ele.location # 驗證碼圖片左上角的坐標 x,y
print("location:",location)
size = code_img_ele.size # 驗證碼標簽對應的長和寬
print("size",size)
# # 左下角和右下角坐標
rangle = (int(location["x"]),int(location["y"]),int(location["x"] + size["width"]),int(location["y"] + size["height"]))
print(rangle)
# 至此驗證碼圖片的區域我們就確定下來了
i = Image.open("aa.png")
code_img_name = 'C:/Users/gpc/Desktop/python/Chaojiying_Python/12306.png'
# crop 根據指定區域進行圖片裁剪
frame = i.crop(rangle)
frame.save(code_img_name)# 保存
將驗證碼圖片提交給超級鷹
超級鷹的使用方法可參考: 07-爬蟲驗證碼破解實戰
# -*- coding: utf-8 -*-
from selenium import webdriver
import time
from PIL import Image
from Chaojiying_Python import chaojiying
from selenium.webdriver import ActionChains
bro = webdriver.Chrome()
url = "https://kyfw.12306.cn/otn/resources/login.html"
bro.get(url)
bro.implicitly_wait(5) #靜默等待最大5秒,保證頁面加載完畢
bro.maximize_window() # 窗口最大化
time.sleep(1)
bro.find_element_by_xpath("/html/body/div[2]/div[2]/ul/li[2]/a").click()
bro.save_screenshot('aa.png')# save_screenshot 將當前頁面進行截圖保存
# 確定驗證碼圖片對應的左上角和右下角坐標(裁剪的區域就確定了)
code_img_ele = bro.find_element_by_xpath('//*[@id="J-loginImg"]')
location = code_img_ele.location # 驗證碼圖片左上角的坐標 x,y
print("location:",location)
size = code_img_ele.size # 驗證碼標簽對應的長和寬
print("size",size)
# # 左下角和右下角坐標
rangle = (int(location["x"]),int(location["y"]),int(location["x"] + size["width"]),int(location["y"] + size["height"]))
print(rangle)
# 至此驗證碼圖片的區域我們就確定下來了
i = Image.open("aa.png")
code_img_name = 'C:/Users/gpc/Desktop/python/Chaojiying_Python/12306.png'
# crop 根據指定區域進行圖片裁剪
frame = i.crop(rangle)
frame.save(code_img_name)# 保存
# 將驗證碼圖片提交給超級鷹進行識別
yanzhengma = chaojiying.Chaojiying_Client.tranformImgCode()
print(yanzhengma)
點擊驗證碼並登錄賬號
# -*- coding: utf-8 -*-
from selenium import webdriver
import time
from PIL import Image
from Chaojiying_Python import chaojiying
from selenium.webdriver import ActionChains
bro = webdriver.Chrome()
url = "https://kyfw.12306.cn/otn/resources/login.html"
bro.get(url)
bro.implicitly_wait(5) #靜默等待最大5秒,保證頁面加載完畢
bro.maximize_window() # 窗口最大化
time.sleep(1)
bro.find_element_by_xpath("/html/body/div[2]/div[2]/ul/li[2]/a").click()
bro.save_screenshot('aa.png')# save_screenshot 將當前頁面進行截圖保存
# 確定驗證碼圖片對應的左上角和右下角坐標(裁剪的區域就確定了)
code_img_ele = bro.find_element_by_xpath('//*[@id="J-loginImg"]')
location = code_img_ele.location # 驗證碼圖片左上角的坐標 x,y
print("驗證碼圖片左上角坐標:",location)
size = code_img_ele.size # 驗證碼標簽對應的高和寬
print("驗證碼圖片的高和寬:",size)
# # 左上角和右下角坐標
rangle = (int(location["x"]),int(location["y"]),int(location["x"] + size["width"]),int(location["y"] + size["height"]))
print("驗證碼圖片左上角和右下角坐標:",rangle)
# 至此驗證碼圖片的區域我們就確定下來了
i = Image.open("aa.png")
code_img_name = 'C:/Users/gpc/Desktop/python/Chaojiying_Python/12306.png'
# crop 根據指定區域進行圖片裁剪
frame = i.crop(rangle)
frame.save(code_img_name)# 保存
# 將驗證碼圖片提交給超級鷹進行識別
yanzhengma = chaojiying.Chaojiying_Client.tranformImgCode()
print("超級鷹識別出來的待點擊的坐標值:",yanzhengma)
all_list = [] # 存儲即將被點擊的點坐標 [[x1,y1],[x2,y2]]
if "|" in yanzhengma:
list_1 = yanzhengma.split("|")
count_1 = len(list_1)
for i in range(count_1):
xy_list = []
x = int(list_1[i].split(",")[0])
y = int(list_1[i].split(",")[1])
xy_list.append(x)
xy_list.append(y)
all_list.append(xy_list)
else:
x = int(yanzhengma.split(",")[0])
y = int(yanzhengma.split(",")[1])
xy_list = []
xy_list.append(x)
xy_list.append(y)
all_list.append(xy_list)
print(all_list)
# 遍歷位置列表,使用動作鏈對每一個列表元素對應的x,y指定的位置進行點擊操作
for l in all_list:
x = l[0]
y = l[1]
ActionChains(bro).move_to_element_with_offset(code_img_ele,x,y).click().perform()#動作鏈
time.sleep(0.5)
# 輸入用戶名密碼
bro.find_element_by_id('J-userName').send_keys('18398141111')
time.sleep(1)
bro.find_element_by_id('J-password').send_keys('11111')
time.sleep(1)
bro.find_element_by_id('J-login').click()
#bro.quit()#退出
滑動模塊破解
加入動作鏈滑動代碼如下
# -*- coding: utf-8 -*-
from selenium import webdriver
import time
from PIL import Image
from Chaojiying_Python import chaojiying
from selenium.webdriver import ActionChains
bro = webdriver.Chrome()
url = "https://kyfw.12306.cn/otn/resources/login.html"
bro.get(url)
bro.implicitly_wait(5) #靜默等待最大5秒,保證頁面加載完畢
bro.maximize_window() # 窗口最大化
time.sleep(1)
bro.find_element_by_xpath("/html/body/div[2]/div[2]/ul/li[2]/a").click()
bro.save_screenshot('aa.png')# save_screenshot 將當前頁面進行截圖保存
# 確定驗證碼圖片對應的左上角和右下角坐標(裁剪的區域就確定了)
code_img_ele = bro.find_element_by_xpath('//*[@id="J-loginImg"]')
location = code_img_ele.location # 驗證碼圖片左上角的坐標 x,y
print("驗證碼圖片左上角坐標:",location)
size = code_img_ele.size # 驗證碼標簽對應的高和寬
print("驗證碼圖片的高和寬:",size)
# # 左上角和右下角坐標
rangle = (int(location["x"]),int(location["y"]),int(location["x"] + size["width"]),int(location["y"] + size["height"]))
print("驗證碼圖片左上角和右下角坐標:",rangle)
# 至此驗證碼圖片的區域我們就確定下來了
i = Image.open("aa.png")
code_img_name = 'C:/Users/gpc/Desktop/python/Chaojiying_Python/12306.png'
# crop 根據指定區域進行圖片裁剪
frame = i.crop(rangle)
frame.save(code_img_name)# 保存
# 將驗證碼圖片提交給超級鷹進行識別
yanzhengma = chaojiying.Chaojiying_Client.tranformImgCode()
print("超級鷹識別出來的待點擊的坐標值:",yanzhengma)
all_list = [] # 存儲即將被點擊的點坐標 [[x1,y1],[x2,y2]]
if "|" in yanzhengma:
list_1 = yanzhengma.split("|")
count_1 = len(list_1)
for i in range(count_1):
xy_list = []
x = int(list_1[i].split(",")[0])
y = int(list_1[i].split(",")[1])
xy_list.append(x)
xy_list.append(y)
all_list.append(xy_list)
else:
x = int(yanzhengma.split(",")[0])
y = int(yanzhengma.split(",")[1])
xy_list = []
xy_list.append(x)
xy_list.append(y)
all_list.append(xy_list)
print("被點擊的坐標位置:",all_list)
# 遍歷位置列表,使用動作鏈對每一個列表元素對應的x,y指定的位置進行點擊操作
for l in all_list:
x = l[0]
y = l[1]
ActionChains(bro).move_to_element_with_offset(code_img_ele,x,y).click().perform()#動作鏈
time.sleep(0.5)
# 輸入用戶名密碼
bro.find_element_by_id('J-userName').send_keys('18398141111')
time.sleep(1)
bro.find_element_by_id('J-password').send_keys('11111')
time.sleep(1)
bro.find_element_by_id('J-login').click()
# 加入動作鏈
div_tag = bro.find_element_by_xpath('//*[@id="nc_1_wrapper"]')
# 對div_tag進行滑動操作
action = ActionChains(bro) #實例化一個動作對象
action.click_and_hold(div_tag) # 點擊且長按不放
for i in range(6):
# perform 讓動作鏈立即執行
action.move_by_offset(20,0).perform() #偏移x20像素,y0像素
time.sleep(0.1)
action.release()
#bro.quit()#退出
結果如下:
京東缺口滑動驗證碼
# -*- coding: utf-8 -*-
from collections import Counter
from PIL import Image
from selenium import webdriver
import time
from selenium.webdriver.common.action_chains import ActionChains
class JDlogin():
def __init__(self):#定義函數,鏈接登錄頁面
self.driver = driver = webdriver.Chrome()#啟動調試工具
self.driver.get('https://passport.jd.com/new/login.aspx')#獲取JD登陸頁面
self.driver.implicitly_wait(5) # 靜默等待最大5秒,保證頁面加載完畢
time.sleep(2)
def get_picture(self):#獲取圖片
#通過xpath尋找按鍵點擊“賬戶登陸”
self.driver.find_element_by_xpath('.//div[@class="login-tab login-tab-r"]/a').click()
time.sleep(1)
#定位賬號輸入框
self.driver.find_element_by_xpath('.//input[@id="loginname"]').send_keys('賬號')
time.sleep(1)
#定位密碼輸入框
self.driver.find_element_by_xpath('.//input[@id="nloginpwd"]').send_keys('密碼')
time.sleep(1)
#定位登陸按鈕,並點擊,此時會展示出驗證碼圖片
self.driver.find_element_by_xpath('.//div[@class="login-btn"]/a').click()
time.sleep(1)
#通過修改JS隱藏滑塊並截屏獲取驗證碼圖片,保存至當前目錄,名為slice.png(雙層圖也是這么干,不過ClassName與xpath需要改動)
js = 'document.getElementsByClassName("JDJRV-smallimg")[0].style.display="none"'
self.driver.execute_script(js)
slice_path = './slice.png'
self.driver.find_element_by_xpath('.//div[@class="JDJRV-bigimg"]').screenshot(slice_path)
time.sleep(1)
#停止1秒后恢復JS改動,回到頁面最初狀態(雙層圖亦然)
js = 'document.getElementsByClassName("JDJRV-smallimg")[0].style.display="block"'
self.driver.execute_script(js)
#將獲得的驗證碼圖片進行處理(灰度化、二值化、降噪)
#雙層圖可以直接進行兩張圖片的比較,而單層圖則需要處理之后進行自身比較,本案例為單層圖事例
def shape(self, w, h, image): # 二值化,將所有的點位,全部換成0或255
tem = 0
for x in range(w):
for y in range(h):
tem += image.getpixel((x, y))
pixel_ave = tem / w / h * 0.7
for x in range(w):
for y in range(h):
p = image.getpixel((x, y))
if p < pixel_ave:
image.putpixel((x, y), 0)
else:
image.putpixel((x, y), 255)
return image
def reducenoise(self, image):#降噪處理
w, h = image.size
for x in range(0, 40): # 處理最左邊
for y in range(h):
image2 = image.putpixel((x, y), 255)
return image
def make_picture(self): # 處理圖片,灰度化與二值化、降噪
im = Image.open('slice.png')
im2 = im.convert("L")
w, h = im2.size
im3 = self.shape(w, h, im2)
im4 = self.reducenoise(im3)
return im3
#計算驗證圖片左邊邊界到缺口左邊邊界的距離(即滑塊拖動距離)
def get_juli(self, image): # 計算距離
w, h = image.size
ls = []
for i in range(31, w - 31):#圖片最左邊放置滑塊,缺口坐標x不可能小於31
for j in range(10, h):
if image.getpixel((i, j)) < 100:
count = 0
for k in range(i, i + 31):
if image.getpixel((k, j)) < 100:
count += 1
else:
break
if count > 27: ls.append(i)
return Counter(ls).most_common(1)[0][0]
#設計拖動軌跡
def get_track(self, distance): # 設計拖動軌跡
ls = [1]
while 1:
i = ls[-1] * 2
ls.append(i)
if sum(ls) > distance * 0.7:
break
ls.append(int(distance - sum(ls)))
return ls
#通過selenium執行拖動滑塊的指令,實現驗證登陸
def drog_btn(self, track): # 拖動滑塊
#定位滑塊
ele = self.driver.find_element_by_xpath('.//div[@class="JDJRV-slide-inner JDJRV-slide-btn"]')
#設計拖動動作鏈(點擊且不放)
ActionChains(self.driver).click_and_hold(ele).perform()
#根據設計的軌跡,實現滑塊拖動
for i in track:
ActionChains(self.driver).move_by_offset(i, 0).perform()#鼠標從當前位置移動到某個坐標
#睡眠0.25秒,偽裝成人的等一下松開鼠標的操作
time.sleep(0.25)
#釋放滑塊,類似於松開鼠標
ActionChains(self.driver).release().perform()
time.sleep(2)
def check(self):#再次嘗試
self.get_picture()
image = self.make_picture()
distance = self.get_juli(image)
track = self.get_track(distance)
self.drog_btn(track)
if __name__ == '__main__':
login = JDlogin()
login.get_picture()
image = login.make_picture()
distance = login.get_juli(image)
track = login.get_track(distance)
login.drog_btn(track)
time_int = 0
while time_int < 5:
input("是否需要再次嘗試")
login.driver.refresh()
login.check()
time_int += 1
ActionChains動作鏈方法列表
click(on_element=None) ——單擊鼠標左鍵
click_and_hold(on_element=None) ——點擊鼠標左鍵,不松開
context_click(on_element=None) ——點擊鼠標右鍵
double_click(on_element=None) ——雙擊鼠標左鍵
drag_and_drop(source, target) ——拖拽到某個元素然后松開
drag_and_drop_by_offset(source, xoffset, yoffset) ——拖拽到某個坐標然后松開
key_down(value, element=None) ——按下某個鍵盤上的鍵
key_up(value, element=None) ——松開某個鍵
move_by_offset(xoffset, yoffset) ——鼠標從當前位置移動到某個坐標
move_to_element(to_element) ——鼠標移動到某個元素
move_to_element_with_offset(to_element, xoffset, yoffset) ——移動到距某個元素(左上角坐標)多少距離的位置
perform() ——執行鏈中的所有動作
release(on_element=None) ——在某個元素位置松開鼠標左鍵
send_keys(*keys_to_send) ——發送某個鍵到當前焦點的元素
send_keys_to_element(element, *keys_to_send) ——發送某個鍵到指定元素