爬虫日常-selenium登录12306,绕过验证

文章目录

  • 前言
  • 代码设计

前言

hello兄弟们,这里是无聊的网友。愉快的周末过去了,欢迎回到学习频道。书接上文,我们说到了再用selenium登录12306时遇到了滑块验证的问题。当前的网站几乎每家都会在登录模块添加一个认证,来规避各种爬虫,而我们则不断的去想办法绕过这些验证模块。目前一些简单的验证如图片拼接,汉字识别的都可以借助如图鉴,超级鹰提供的功能解决。而主流的流行应用的验证绕过则需要非常复杂的步骤。我们就有点自知之明,先能够做到简单的绕过就好。
爬虫日常-selenium登录12306,绕过验证_第1张图片就拿12306为例,目前还只是最简单的滑块验证,还好不是类似哔哩哔哩的极验类的滑块验证,所以我们趁着它简单先拿它开刀​

爬虫日常-selenium登录12306,绕过验证_第2张图片我们可以看到在输入账号密码后,页面就会跳出滑块认证,依旧是先分析再动手

按照正常思路,先点击到滑块认证,然后鼠标点击滑块,拖动到最边上。我们首先右键检查滑块认真,看看验证模块有没有存在iframe中

爬虫日常-selenium登录12306,绕过验证_第3张图片检查完发现div并没有被包裹在iframe中,就存在页面源码中,我们就可以直接通过find_element定位到此处并进行点击动作

代码设计

先放上上一期的代码

from selenium.webdriver import Chrome
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By


# 定义登录方法
def login(user, pwd):
    login_choice = web.find_element(By.XPATH, '//*[@id="toolbar_Div"]/div[2]/div[2]/ul/li[1]')
    # 点击账号密码登录方式
    login_choice.click()
    web.find_element(By.XPATH, '//*[@id="J-userName"]').send_keys(user)  # 向账号框传入账号信息
    web.find_element(By.XPATH, '//*[@id="J-password"]').send_keys(pwd)  # 向密码框传入密码
    # 定位到登录按钮并点击
    web.find_element(By.XPATH, '//*[@id="J-login"]').click()


if __name__ == '__main__':
    opt = Options()
    opt.add_experimental_option('excludeSwitches', ['enable-automation'])  # 去除浏览器顶部显示受自动化程序控制
    opt.add_experimental_option('detach', True)  # 规避程序运行完自动退出浏览器
    web = Chrome(options=opt)
    web.get('https://kyfw.12306.cn/otn/resources/login.html')
    user = ''  # 此处输入账号
    pwd = ''   # 此处输入密码
    login(user, pwd)

按照设计思路,我们应当在登录方法处添加模拟点击滑块的代码
到了这一步,学完基础的同学就应该想到要借助ActionChains,ActionChains模拟鼠标操作的常用方法。使用click()方法可以进行鼠标的单击操作,此外还提供了有关双击、右击、悬停、鼠标拖动等功能的方法,这里不一一阐述了。

设计代码如下

    span = web.find_element(By.XPATH, '//*[@id="nc_2_n1z"]')  # 首先定位到滑块
    action = ActionChains(web)
    action.click_and_hold(span).move_by_offset(300, 0).perform() # click_and_hold代表点击并保持点击动作。move_by_offset(x, y),其中x代表水平移动距离,y代表垂直移动距离
    

爬虫日常-selenium登录12306,绕过验证_第4张图片爬虫日常-selenium登录12306,绕过验证_第5张图片可以看到整个滑块的水平长度为340​而需要移动的小滑块为38.4的宽度。所以大致需要移动的距离为340-38.4。如果move_by_offset的x参数过大可以导致程序报错超出滑框宽度,在循环中若移动的参数过小可能到达不了最右侧或者超时认证。因此此处我直接一次性滑动300.
编写完运行检测效果
爬虫日常-selenium登录12306,绕过验证_第6张图片可以看到第一次的运行失败,报错信息为滑块验证element没有定位到。那么为什么会出现这样的错误呢。是因为我们的速度太快了
爬虫日常-selenium登录12306,绕过验证_第7张图片
因为我们的点击请求过快,导致页面的滑块验证模块还没有跳转出来就直接进行点击请求了,解决的方法也很简单,可以直接使用time.sleep进行强制睡眠。但我们不建议这样使用,最好是采用显示等待的方法对其处理。

我们都知道显式等待也称为智能等待,针对指定元素定位指定等待时间,在指定时间范围内进行元素查找,找到元素则直接返回,如果在超时还没有找到元素,则抛出异常,显示等待是 selenium 当中比较灵活的一种等待方式,他的实现原理其实是通过 while 循环不停的尝试需要进行的操作。那么知道了原理后就直接上手用它。

在定位到滑块验证并点击前设置显示等待。需要下面两个包配合使用

from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
     # 此处还去掉了点击滑块验证的操作
    # 设置显示等待直到滑块的span标签被定位到
    WebDriverWait(web, 0.5, 0.05).until(EC.presence_of_element_located((By.ID, 'nc_1_n1z')))
    span = web.find_element(By.ID, 'nc_1_n1z')  # 首先定位到滑块

WebDriverWait()中的参数主要为等待时间和刷新时间,经过我的测试0.5为我的程序最少的需要的等待时间,再少程序就要报错,同样0.05为最少刷新时间
这个是和个人电脑与网速有关的,报错的同学可以尝试修改
编写后在再次测试
爬虫日常-selenium登录12306,绕过验证_第8张图片
ok,最后运行成功。成功绕过12396的滑块认证。老规矩运行成功放源码

from selenium.webdriver import Chrome
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
from selenium.webdriver import ActionChains
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC


# 定义登录方法
def login(user, pwd):
    login_choice = web.find_element(By.XPATH, '//*[@id="toolbar_Div"]/div[2]/div[2]/ul/li[1]')
    # 点击账号密码登录方式
    login_choice.click()

    username = web.find_element(By.XPATH, '//*[@id="J-userName"]')  # 向账号框传入账号信息
    passwd = web.find_element(By.XPATH, '//*[@id="J-password"]')  # 向密码框传入密码
    username.click()
    username.send_keys(user)
    passwd.click()
    passwd.send_keys(pwd)
    # 定位到登录按钮并点击
    web.find_element(By.XPATH, '//*[@id="J-login"]').click()
    # 设置显示等待直到滑块的span标签被定位到
    WebDriverWait(web, 0.5, 0.05).until(EC.presence_of_element_located((By.ID, 'nc_1_n1z')))
    span = web.find_element(By.ID, 'nc_1_n1z')
    action = ActionChains(web)
    action.click_and_hold(span).move_by_offset(300, 0).perform() # click_and_hold代表点击并保持点击动作。move_by_offset(x, y),其中x代表水平移动距离,y代表垂直移动距离


if __name__ == '__main__':
    opt = Options()
    opt.add_experimental_option('excludeSwitches', ['enable-automation'])  # 去除浏览器顶部显示受自动化程序控制
    opt.add_experimental_option('detach', True)  # 规避程序运行完自动退出浏览器
    web = Chrome(options=opt)
    web.get('https://kyfw.12306.cn/otn/resources/login.html')
    # 解除浏览器特征识别selenium
    script = 'Object.defineProperty(navigator,"webdriver", {get: () => false,});'
    web.execute_script(script)
    user = ''  # 此处输入账号
    pwd = ''   # 此处输入密码
    login(user, pwd)

今天先告一段落,明天在和大家接着研究如何在登录后选购票。麻烦点个赞哦兄弟们。
爬虫日常-selenium登录12306,绕过验证_第9张图片

你可能感兴趣的:(爬虫日常,爬虫,python,selenium)