首先是找出登录界面各控件的位置,我尝试从网页源代码寻找,但找不到,网上也没有很好的讲解,经过多次尝试发现了寻找控件的方法.
即网页的检查功能。
打开检查界面后可看到如下图像:
从…中即可对应左侧UI找出各控件的位置与id等信息。如下图:
下面进行登陆代码的书写:
def login(self):
driver = webdriver.Firefox()
driver.get(self.url)
driver.find_element_by_id('login-username').send_keys(self.username) #输入账号
driver.find_element_by_id('login-passwd').send_keys(self.password) #输入密码
driver.find_element_by_class_name('btn-login').click()
但因为被检测为机器人无法出现滑动验证界面。后来经过查阅资料得知可以通过在定位控件后sleep()来模拟人的操作,进而成功得出滑动验证界面。
def login(self):
driver = webdriver.Firefox()
driver.get(self.url)
driver.find_element_by_id('login-username').send_keys(self.username) #输入账号
driver.find_element_by_id('login-passwd').send_keys(self.password) #输入密码
button = driver.find_element_by_class_name('btn-login')
time.sleep(1)
button.click()
接下来是滑块验证的部分,主要参考这篇博客的方法。
这里用到的图像处理包image需要导入包PIL,但python3.6不能导入PIL,需要导入Pillow后使用。pillow的导入可以下载后安装(下载网址)。
下面附上全部代码:
# coding=utf-8
from PIL import Image
import requests
from selenium import webdriver
import time
from selenium.webdriver import ActionChains
class loginbli(object):
def __init__(self): #初始化一些信息
self.left = 70 # 定义一个左边的起点 缺口一般离图片左侧有一定的距离 有一个滑块
self.url = 'https://passport.bilibili.com/login'
self.username = ''
self.password = ''
self.driver = webdriver.Firefox()
def login(self):
self.driver.get(self.url)
self.driver.maximize_window()
self.driver.find_element_by_id('login-username').send_keys(self.username) #输入账号
self.driver.find_element_by_id('login-passwd').send_keys(self.password) #输入密码
button = self.driver.find_element_by_class_name('btn-login')
time.sleep(1)
button.click()
time.sleep(1)
def getimg(self): #获得验证图片及完整图片
img = self.driver.find_element_by_class_name('geetest_canvas_bg')
time.sleep(1)
img.screenshot('E:\\img1.png')
js = 'var change = document.getElementsByClassName("geetest_canvas_fullbg");change[0].style = "display:block;"'
self.driver.execute_script(js)
time.sleep(1)
img2 = self.driver.find_element_by_class_name('geetest_canvas_fullbg')
time.sleep(1)
img2.screenshot('E:\\img2.png')
def is_similar(self, image1, image2, x, y):
pixel1 = image1.load()[x, y]
pixel2 = image2.load()[x, y]
threshold = 60
if abs(pixel1[0] - pixel2[0]) < threshold and abs(pixel1[1] - pixel2[1]) < threshold and abs(
pixel1[2] - pixel2[2]) < threshold:
return True
else:
return False
def get_diff_location(self): # 获取缺口图起点
captcha1 = Image.open('E:\\img1.png')
captcha2 = Image.open('E:\\img2.png')
for x in range(self.left, captcha1.size[0]): # 从左到右 x方向
for y in range(captcha1.size[1]): # 从上到下 y方向
if not self.is_similar(captcha1, captcha2, x, y):
return x # 找到缺口的左侧边界 在x方向上的位置
def get_move_track(self, gap):
track = [] # 移动轨迹
current = 0 # 当前位移
# 减速阈值
mid = gap * 4 / 5 # 前4/5段加速 后1/5段减速
t = 0.2 # 计算间隔
v = 0 # 初速度
move = 0
while current < gap and current + move < gap:
if current < mid:
a = 3 # 加速度为+3
else:
a = -3 # 加速度为-3
v0 = v # 初速度v0
v = v0 + a * t # 当前速度
move = v0 * t + 1 / 2 * a * t * t # 移动距离
current += move # 当前位移
track.append(round(move)) # 加入轨迹
move = gap - current
track.append(round(move))
return track
def move_slider(self, track):
slider = self.driver.find_element_by_class_name('geetest_slider_button')
ActionChains(self.driver).click_and_hold(slider).perform()
time.sleep(1)
y = 0
for x in track: # 只有水平方向有运动 按轨迹移动
ActionChains(self.driver).move_by_offset(xoffset=x, yoffset=0).perform()
y += x
time.sleep(1)
ActionChains(self.driver).release().perform() # 松开鼠标
log = loginbli()
log.login()
log.getimg()
gap = log.get_diff_location()#缺口左起点位置
gap = gap -10
# 减去滑块左侧距离图片左侧在x方向上的距离 即为滑块实际要移动的距离
track = log.get_move_track(gap)
print("移动轨迹",track)
log.move_slider(track)
本代码是在FireFox上进行的,大部分时候滑块能成功滑到正确位置,但会被判定为机器人,所以此算法仍需优化,仅用于练习和初学使用。
注:需要把电脑显示比例调为100%。