1. 驱动下载
selenium模拟浏览器登录需要下载对应版本驱动
Firefox驱动:https://github.com/mozilla/geckodriver/releases/
Chrome驱动:http://chromedriver.storage.googleapis.com/index.html
下载对应版本即可, Chrome驱动32位没关系,可以正常使用的
注意:因为12306会检测webdriver,所以Firefox新版(88以后)的浏览器暂时没办法解决这个问题,只能使用Chrome
驱动下载后 可以添加到代码所在文件夹(executable_path='./chromedriver.exe')或者当前项目的环境文件夹里-python.exe所在文件夹(调用时候不需要+executable_path)
2. 代码编写
2.1避免webdriver检测
import time from selenium import webdriver options = webdriver.ChromeOptions() options.add_argument('--disable-blink-features=AutomationControlled') # 避免webdriver检测 browser = webdriver.Chrome(options=options) # 因为我的chrome.exe在环境目录里面,所以不用写 executable_path=’、、、‘
12306会自动检测webdriver,可以在控制台输入:
window.navigator.webdriver
查看,未检出应该是False,只要检测出(True),则后面的滑块验证是无法通过的
2.2 正常获取网站,此处不多赘述
url = 'https://kyfw.12306.cn/otn/resources/login.html' browser.get(url=url) js = 'return window.navigator.webdriver' print(browser.execute_script(js)) # 可以直接在终端输出webdriver检测结果
# 从页面直接检查元素(账号登陆),然后复制xpath即可获取到当前按钮 btn = browser.find_element_by_xpath('//*[@id="toolbar_Div"]/div[2]/div[2]/ul/li[2]/a') btn.click() print(browser.execute_script(js)) time.sleep(2) # 点击后需要等待1-2秒,确保账号登录页面加载出来。若后面获取元素失败,大概率可能是时间不够动态加载出来 account = browser.find_element_by_xpath('//*[@id="J-userName"]') account.send_keys('phone number') pwd = browser.find_element_by_xpath('//*[@id="J-password"]') pwd.send_keys('password') # 输入账号密码 login = browser.find_element_by_xpath('//*[@id="J-login"]') login.click() 点击登录按钮出现滑块验证 print(browser.execute_script(js)) time.sleep(2)
代码里面的三个webdriver检测输出为false,说明未被检测到, OK
2.3 滑块验证
通过查看源码,手动测试查看出滑块滑动长度为300px,若一次滑动不通过出现以下页面,则需点击刷新,重复以上步骤,所以采用while和try结合
while True: try: action = webdriver.ActionChains(browser) # 利用行为链,持续按住并拖拽 span = browser.find_element_by_xpath('//*[@id="nc_1_n1z"]') # 获取滑块 action.drag_and_drop_by_offset(span, 330, 0).perform() # 按住并拖动 >300px即可,选用330绰绰有余 # action.click_and_hold(span).perform() # action.move_by_offset(xoffset=300,yoffset=0).perform() 另一张拖动 action.release() # 释放 print(browser.execute_script(js)) time.sleep(2) a = browser.find_element_by_xpath('//*[@id="nc_1_refresh1"]') # 查找刷新按钮,如果没有说明登录成功,执行except跳出循环 a.click() # 如果刚刚滑动失败,则点击刷新,重新滑动 time.sleep(5) except Exception as e: print(e) break
3 最终验证通过,结果如下
验证通过啦