当前位置:脚本大全 > > 正文

selenium是否登录成功(使用selenium模拟登录解决滑块验证问题的实现)

时间:2021-10-08 00:19:40类别:脚本大全

selenium是否登录成功

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

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

1.登录入口

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

部分代码实现:

  • ?
  • 1
  • 2
  • driver = webdriver.chrome()
  • driver.get(url)
  • 2.点击“账号密码登录”

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

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

    selenium是否登录成功(使用selenium模拟登录解决滑块验证问题的实现)

    部分代码实现:

  • ?
  • 1
  • 2
  • 3
  • 4
  • 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.输入账号、密码并点击登录

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

  • ?
  • 1
  • 2
  • 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是否登录成功(使用selenium模拟登录解决滑块验证问题的实现)

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

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

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

    selenium是否登录成功(使用selenium模拟登录解决滑块验证问题的实现)

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

    selenium是否登录成功(使用selenium模拟登录解决滑块验证问题的实现)

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

    3)切换frame

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

  • ?
  • 1
  • 2
  • 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类,部分代码如下:

  • ?
  • 1
  • 2
  • 3
  • 4
  • 5
  • 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新闻的滑块验证对这方面好像要求不是很严格:

  • ?
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 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是否登录成功(使用selenium模拟登录解决滑块验证问题的实现)

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

    selenium是否登录成功(使用selenium模拟登录解决滑块验证问题的实现)

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

    selenium是否登录成功(使用selenium模拟登录解决滑块验证问题的实现)

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

    7)重试

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

  • ?
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • # 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.小结

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

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

    以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持开心学习网。

    原文链接:https://blog.csdn.net/u012067766/article/details/79793264

    上一篇下一篇

    猜您喜欢

    热门推荐