使用selenium模拟登录解决滑块验证问题的实现


Posted in Python onMay 10, 2019

本次主要是使用selenium模拟登录网页端的TX新闻,本来最开始是模拟请求的,但是某一天突然发现,部分账号需要经过滑块验证才能正常登录,如果还是模拟请求,需要的参数太多了,找的心累。不过好在TX的滑块验证是他们自己开发的,没有极验那么复杂,当然相反的,想要模拟就得自己去一点点探索了,毕竟对极验滑块的破解,网上已经可以找到现成的代码来用了。下面说一下模拟的实现过程和我遇见的问题。

1.登录入口

我是通过点击打开链接来当做登录入口的

部分代码实现:

driver = webdriver.Chrome()
driver.get(url)

2.点击“账号密码登录”

selenium可以实现对网页元素的定位,我这里是通过id属性来定位“帐号密码登录”按钮的。这里需要注意的是,有时候可能会因为网络不好等问题导致加载登录入口页会很慢,所以在点击“帐号密码登录”按钮前,需要做一个判断:判断代表“帐号密码登录”的HTML元素是否已经加载完成。

“账号密码登录”按钮的id属性截图:

使用selenium模拟登录解决滑块验证问题的实现

部分代码实现:

element = WebDriverWait(driver, 5, 0.5).until(
		EC.presence_of_element_located((By.ID, "switcher_plogin"))
	) # from selenium.webdriver.common.by import By
element.click()

3.输入账号、密码并点击登录

这一步比较简单,直接上代码:

driver.find_element_by_id('u').send_keys('123456') # 输入用户名
driver.find_element_by_id('p').send_keys('ccccc')  # 输入密码
driver.find_element_by_id('login_button').click()  # 点击登录

4.滑块验证过程

1)简要说明

因为主要目的就是为了模拟滑块验证,所以在输入用户名和密码的时候直接选择输入“123456”和“ccccc”,这样就必然会跳到滑块验证的页面:

使用selenium模拟登录解决滑块验证问题的实现

接下来的问题就是如何模拟滑动的过程。这里首先要说一下,经过多次测试发现,TX的滑块验证每次需要拖动的距离是有一定范围的,“缺口”部分的位置基本上都在靠右侧的一面,不像极验的滑块验证,“缺口”部分可能出现在任意的位置,这样在实现“滑动”过程前,就必须判断每次滑动的距离是多少。所以,对于TX的滑块验证,只要设置一个大概的距离“模拟滑动”即可,失败的时候可以通过增减移动距离进行重试,后面会进一步说明。

2)为什么找不到“蓝色滑块”

前面已经点击了“登录”并跳转到“安全验证”的页面,接着就是去模拟“拖动”截图中的“蓝色滑块”,所以首先要告诉driver,代表“蓝色滑块”的html元素是什么。代表“蓝色滑块”的html元素截图:

使用selenium模拟登录解决滑块验证问题的实现

通过上面的截图可以知道,id值为"tcaptcha_drag_button"的div标签代表的就是“蓝色滑块”,所以最开始我是直接尝试去拖动它,但是这时候发现报错了,部分截图如下:

使用selenium模拟登录解决滑块验证问题的实现

报错的原因很明显,在当前得到的所有html元素中,找不到id值为"tcaptcha_drag_button"的div标签。这是为什么?

3)切换frame

为什么出现上面的问题?通过查找相关的资料才知道,在跳转到“安全验证”的页面的时候,“进入”了一个新的frame,可以理解为,在“登录页面”嵌套了一个“验证页面”,而当前的driver加载的html元素全部都是“登录页面”的,想要找到并拖动“蓝色滑块”,就要先切换到“验证页面”,这里通过driver.switch_to方法实现:

iframe = driver.find_element_by_xpath('//iframe') # 找到“嵌套”的iframe
driver.switch_to.frame(iframe)  # 切换到iframe

4)模拟拖动

切换到iframe之后,就可以通过driver.find_element_by_id('tcaptcha_drag_button')找到“蓝色滑块”并拖动它了。拖动操作会用到selenium.webdriver的ActionChains类,部分代码如下:

button = driver.find_element_by_id('tcaptcha_drag_button')    # 找到“蓝色滑块”
action = ActionChains(driver)            # 实例化一个action对象
action.click_and_hold(button).perform()  # perform()用来执行ActionChains中存储的行为
action.reset_actions()
action.move_by_offset(180, 0).perform()  # 移动滑块

5)构造移动轨迹

为了使拖动过程模拟的更“真实”,可以构造一个滑动轨迹,我这里也是参考了别人的代码看这里,简单实现了一下,实际上TX新闻的滑块验证对这方面好像要求不是很严格:

def get_track(distance):
	track = []
	current = 0
	mid = distance * 3 / 4
	t = 0.2
	v = 0
	while current < distance:
		if current < mid:
			a = 2
		else:
			a = -3
		v0 = v
		v = v0 + a * t
		move = v0 * t + 1 / 2 * a * t * t
		current += move
		track.append(round(move))
	return track

6)如何确定已经“验证成功”了

接下来的问题就是,我如何告诉程序,已经“验证成功”了呢?经过测试发现,当拖动滑块完成拼图“验证成功”后,网页又从“安全验证”的页面又跳回了“登录页面”,滑动前截图:

使用selenium模拟登录解决滑块验证问题的实现

滑动验证成功的截图:

使用selenium模拟登录解决滑块验证问题的实现

成功后跳转回“登录”页面:

使用selenium模拟登录解决滑块验证问题的实现

通过上面的截图我们可以知道,在“验证通过”之前,在“安全验证”页面我们一直可以看到“拖动下方滑块完成拼图”的文字提示,也就是说,如果验证没有通过,那么在当前的所有html元素中,我们是可以找到文本为“拖动下方滑块完成拼图”的标签的:

使用selenium模拟登录解决滑块验证问题的实现

通过截图可以知道,该标签的class为"tcaptcha-title",通过driver.find_element_by_class_name('tcaptcha-title').text来判断验证是否成功。

7)重试

前面说了,我们可以通过提前设置一个“可能的”值当初始距离来移动滑块,如果移动的距离“过长”,就减小该值当做下次移动的距离,所以可以加一个while循环。以上过程实现的完整代码如下:

# encoding=utf8
 
from time import sleep
from selenium import webdriver
from selenium.webdriver import ActionChains
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
 
url = 'https://xui.ptlogin2.qq.com/cgi-bin/xlogin?&low_login=0&appid=636014201&target=self&border_radius=1&maskOpacity=40&s_url=http%3A//www.qq.com/qq2012/loginSuccess.htm'
 
def get_track(distance):
	track = []
	current = 0
	mid = distance * 3 / 4
	t = 0.2
	v = 0
	while current < distance:
		if current < mid:
			a = 2
		else:
			a = -3
		v0 = v
		v = v0 + a * t
		move = v0 * t + 1 / 2 * a * t * t
		current += move
		track.append(round(move))
	return track
 
def main():
	driver = webdriver.Chrome()
	driver.set_window_position(900, 10)
	driver.get(url)
	# 检测id为"switcher_plogin"的元素是否加在DOM树中,如果出现了才能正常向下执行
	element = WebDriverWait(driver, 5, 0.5).until(
		EC.presence_of_element_located((By.ID, "switcher_plogin"))
	)
	element.click()
 
	sleep(1)
	# 输入用户名和密码
	driver.find_element_by_id('u').clear()
	driver.find_element_by_id('u').send_keys('123456')
	driver.find_element_by_id('p').clear()
	driver.find_element_by_id('p').send_keys('ccccc')
	sleep(1)
	# 点击登录
	driver.find_element_by_id('login_button').click()
 
	sleep(5)
 
	# 切换iframe
	try:
		iframe = driver.find_element_by_xpath('//iframe')
	except Exception as e:
		print 'get iframe failed: ', e
	sleep(2)	# 等待资源加载
	driver.switch_to.frame(iframe)
 
	# 等待图片加载出来
	WebDriverWait(driver, 5, 0.5).until(
		EC.presence_of_element_located((By.ID, "tcaptcha_drag_button"))
	)
	try:
		button = driver.find_element_by_id('tcaptcha_drag_button')
	except Exception as e:
		print 'get button failed: ', e
 
	sleep(1)
	# 开始拖动 perform()用来执行ActionChains中存储的行为
	flag = 0
	distance = 195
	offset = 5
	times = 0
	while 1:
		action = ActionChains(driver)
		action.click_and_hold(button).perform()
		action.reset_actions()	# 清除之前的action
		print distance
		track = get_track(distance)
		for i in track:
			action.move_by_offset(xoffset=i, yoffset=0).perform()
			action.reset_actions()
		sleep(0.5)
		action.release().perform()
		sleep(5)
 
		# 判断某元素是否被加载到DOM树里,并不代表该元素一定可见
		try:
			alert = driver.find_element_by_class_name('tcaptcha-title').text
		except Exception as e:
			print 'get alert error: %s' % e
			alert = ''
		if alert:
			print u'滑块位移需要调整: %s' % alert
			distance -= offset
			times += 1
			sleep(5)
		else:
			print '滑块验证通过'
			flag = 1
			driver.switch_to.parent_frame()    # 验证成功后跳回最外层页面
			break
 
	sleep(2)
	driver.quit()
	print "finish~~"
	return flag
 
if __name__ == '__main__':
	main()

5.小结

其实上面的代码还可以进一步“优化”。例如,当尝试三次滑动后如果仍然没有“验证成功”,就应该主动跳回“登录”页面,重新输入账号密码登录,进入下一次验证过程,而不是无休止的进行“滑块验证”。除此之外,以上只是对“滑块验证”部分进行了分析和模拟,实际情况是,通过了“滑块验证”后,有可能账号或密码错误了,这时候是不是应该重新输入账号密码进入新一轮验证过程呢?

所以,以上代码还有待继续完善,也欢迎看到这篇博文的人多多指正不足之处。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python写的服务监控程序实例
Jan 31 Python
用Python的pandas框架操作Excel文件中的数据教程
Mar 31 Python
python内存管理分析
Apr 08 Python
python使用wxPython打开并播放wav文件的方法
Apr 24 Python
详解Python 装饰器执行顺序迷思
Aug 08 Python
python 随机生成10位数密码的实现代码
Jun 27 Python
解决Python对齐文本字符串问题
Aug 28 Python
postman和python mock测试过程图解
Feb 22 Python
Windows下Anaconda安装、换源与更新的方法
Apr 17 Python
python 使用xlsxwriter循环向excel中插入数据和图片的操作
Jan 01 Python
Python超简单容易上手的画图工具库推荐
May 10 Python
python process模块的使用简介
May 14 Python
python队列Queue的详解
May 10 #Python
使用Python的OpenCV模块识别滑动验证码的缺口(推荐)
May 10 #Python
详解python中的线程与线程池
May 10 #Python
Python实现的爬取百度贴吧图片功能完整示例
May 10 #Python
Django框架文件上传与自定义图片上传路径、上传文件名操作分析
May 10 #Python
Django框架实现分页显示内容的方法详解
May 10 #Python
Django框架验证码用法实例分析
May 10 #Python
You might like
discuz Passport 通行证 整合笔记
2008/06/30 PHP
php屏蔽错误及提示的方法
2020/05/10 PHP
发布一个高效的JavaScript分析、压缩工具 JavaScript Analyser
2007/11/30 Javascript
js压缩工具 yuicompressor 使用教程
2010/03/31 Javascript
Javascript 检测键盘按键信息及键码值对应介绍
2013/01/03 Javascript
vue.js语法及常用指令
2017/10/29 Javascript
vue 通过下拉框组件学习vue中的父子通讯
2017/12/19 Javascript
微信小程序中使用ECharts 异步加载数据实现图表功能
2018/07/13 Javascript
jQuery实现左右两个列表框的内容相互移动功能示例
2019/01/27 jQuery
浅谈React Native 传参的几种方式(小结)
2019/05/21 Javascript
解决layui 三级联动下拉框更新时回显的问题
2019/09/03 Javascript
借助云开发实现小程序短信验证码的发送
2020/01/06 Javascript
vue+高德地图实现地图搜索及点击定位操作
2020/09/09 Javascript
关于javascript中的promise的用法和注意事项(推荐)
2021/01/15 Javascript
Python抓取聚划算商品分析页面获取商品信息并以XML格式保存到本地
2018/02/23 Python
新手常见6种的python报错及解决方法
2018/03/09 Python
用python打印菱形的实操方法和代码
2019/06/25 Python
python logging模块的使用总结
2019/07/09 Python
python matplotlib拟合直线的实现
2019/11/19 Python
Python partial函数原理及用法解析
2019/12/11 Python
kafka监控获取指定topic的消息总量示例
2019/12/23 Python
tensorflow自定义激活函数实例
2020/02/04 Python
Python新手学习装饰器
2020/06/04 Python
解决Keyerror ''acc'' KeyError: ''val_acc''问题
2020/06/18 Python
常用的四种CSS透明属性介绍
2014/04/12 HTML / CSS
使用canvas绘制贝塞尔曲线
2014/12/17 HTML / CSS
鞋子女王塔玛拉·梅隆同名奢侈品牌:Tamara Mellon
2017/11/22 全球购物
俄罗斯品牌服装在线商店:VIPAVENUE
2020/08/10 全球购物
大三预备党员入党思想汇报
2014/01/08 职场文书
村抢险救灾方案
2014/05/09 职场文书
工作会议方案
2014/05/21 职场文书
学校感恩教育活动总结
2014/07/07 职场文书
我的中国梦演讲稿1000字
2014/08/19 职场文书
2015元旦联欢晚会结束语
2014/12/14 职场文书
综治目标管理责任书
2015/05/11 职场文书
解析在浏览器地址栏输入一个URL后发生了什么
2021/06/21 Servers