IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 开发测试 -> Python+Selenium实现12306模拟登录 -> 正文阅读

[开发测试]Python+Selenium实现12306模拟登录

最近在学python爬虫,学习到了selenium的使用,看网上有很多使用selenium模拟登录12306网站的文章,于是自己也尝试了一下。期间遇到了一些问题,也参考了很多大佬的文章最终得到了解决,在这里记录下来,作为自己学习之用。

首先我们到12306的登录页面,分析一下登录流程。打开登录页面后,默认是扫码登录,我们点击切换到账号登录,然后输入用户名密码,点击立即登录。这时会出来一个验证窗口,可选滑窗验证和短信验证,默认是滑窗验证。我们拖动滑块,验证通过后如果用户名密码正确,url就会跳转到正常登录页面;如果用户名密码错误会出来错误提示。由于12306网站一直在升级,现在的登录流程跟之前好像不太一样了,我记得之前的验证流程还有选择包含指定物体的图片,目前应该是没有了,处理起来也更简单一些。

分析完后,我们可以用selenium来模拟登录了。先上完整代码,然后再说说遇到的问题。

import time
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver import ActionChains
from selenium.webdriver import ChromeOptions
from selenium.common.exceptions import TimeoutException, NoSuchElementException
import getpass

class Login12306():
    # Chrome浏览器绕过webdriver检测,可以成功滑窗
    # 这种方式浏览器没监测到是自动测试工具
    def __init__(self, url, login_user, login_passwd):
        option = ChromeOptions()
        option.add_experimental_option('excludeSwitches', ['enable-automation'])
        self.driver = webdriver.Chrome(options=option)
        self.driver.get(url)
        script = 'Object.defineProperty(navigator, "webdriver", {get:()=>undefined,});'
        self.driver.execute_script(script) 
        self.driver.maximize_window()
        self.login_user = login_user
        self.login_passwd = login_passwd
        self.init_url = url
    
    def Login(self):
        # 点击选择账号登录
        wait = WebDriverWait(self.driver, 60, 0.1)
        account_login = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, '.login-hd-account a')))
        account_login.click()

        # 输入用户名密码
        user_input = self.driver.find_element(By.CSS_SELECTOR, 'input#J-userName')
        user_input.send_keys(self.login_user)
        time.sleep(1)
        passwd_input = self.driver.find_element(By.CSS_SELECTOR, 'input#J-password')
        passwd_input.send_keys(self.login_passwd)
        time.sleep(1)
        login_btn = self.driver.find_element_by_css_selector('div.login-btn a#J-login')
        login_btn.click()

        # 滑窗验证处理
        time.sleep(5)
        span = self.driver.find_element_by_css_selector('#nc_1_n1z')    
        time.sleep(1)
        actions = ActionChains(self.driver)
        time.sleep(2)
        actions.click_and_hold(span)
        actions.drag_and_drop_by_offset(span, 300, 0)
        actions.perform()

        # 通过url变化与否判断是否登录成功
        time.sleep(2)
        print('current_url: ', self.driver.current_url)
        if self.driver.current_url == self.init_url:
            # 网页没跳转, 判断是否提示错误信息
            err_login = self.driver.find_element_by_css_selector('div.login-error')
            if err_login:
                if err_login.is_displayed():
                    print('Login Error!')
        else:
            try:
                # 登录成功后,关闭弹出的对话框
                modal = self.driver.find_element_by_css_selector('div.modal')
                confirm_btn = self.driver.find_element_by_css_selector('div.modal > div.modal-ft > a')
                confirm_btn.click()
            except NoSuchElementException:
                print('NoSuchElementException')        

def main():
    url = 'https://kyfw.12306.cn/otn/resources/login.html'
    login_user = input("Input Username: ")
    login_passwd = getpass.getpass("Input Password: ")
    global login # 避免chrome浏览器驱动在程序执行完后自动关闭浏览器
    login = Login12306(url, login_user, login_passwd)
    login.Login()

if __name__ == '__main__':
    main()

说说遇到的几个问题:

第一个问题:关于网站对selenium等自动化测试工具的反爬处理

一开始我是直接用selenium驱动浏览器打开网页的,此时浏览器打开后会有如下显示:

这说明浏览器已经检测到是自动化工具在控制它。在滑窗验证环节中,出现了如下错误:

?

?拖动滑块后出现了错误提示,开始我以为是selenium做滑窗动作的时候出了问题,但是只要我用selenium打开了浏览器,即使手动拖动滑块还是会出现这个错误提示。后来在网上搜索了一下,发现应该是网站通过js获取了webdriver的属性值。这个值在使用selenium等自动化测试工具时是true,而正常打开网页时是false或者undefined。

?检测到这个值是true后,可能就会采取一些反爬措施,比如滑块验证错误。

最终通过这个博客得到了解决。

option = ChromeOptions()
option.add_experimental_option('excludeSwitches', ['enable-automation'])
self.driver = webdriver.Chrome(options=option)
self.driver.get(url)
script = 'Object.defineProperty(navigator, "webdriver", {get:()=>undefined,});'
self.driver.execute_script(script) 

这个代码我其实并没有完全理解,我尝试了一下不配置option选项,只执行修改webdriver值的脚本,浏览器还是会提示是自动化测试工具,但滑窗验证也能通过。此时查看webdriver的值也已经变成了undefined。如果配置了option选项,浏览器就不会出现自动测试工具的提示了。

另外还有一点疑惑:这个js脚本是在get之后修改webdriver的值,这个时候网站应该已经获取了webdriver的值,为什么还能有效呢?我看有些博客也提到了这个问题,而且也提到了其他的解决方法,本人对js不太熟,也没有继续深究了,总之问题得到了解决。

我尝试了用这个方法也是可以的

self.driver = webdriver.Chrome()
self.driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {
    "source": """
        Object.defineProperty(navigator, 'webdriver', {
        get: () => undefined
    })"""
})
self.driver.get(url)

同时我测试了一下用Firefox,也是同样的问题,最终也是通过执行上述的script脚本得到了解决。

self.driver = webdriver.Firefox()
self.driver.get(url)
script = 'Object.defineProperty(navigator, "webdriver", {get:()=>undefined,});'
self.driver.execute_script(script) 
self.driver.maximize_window()

第二个问题:chrome浏览器自动退出问题

当我用chrome浏览器登录成功后,程序退出时,网页也关闭了,如果使用firefox则没有问题。最终参考这篇文章解决了问题。

global login # 避免chrome浏览器驱动在程序执行完后自动关闭浏览器

?主要参考文章:

python爬虫实战之旅(12306模拟登录+验证码识别+滑块验证)_KQ的博客-CSDN博客

WebDriver被识别反爬虫解决办法(Chrome正受到自动化测试软件的控制)_成都_杨洋-CSDN博客_webdriver 反爬虫

反反爬虫(0) :还在用 selenium 裸爬吗? 你已经被盯上了!破解WebDriver反爬虫_zzzzls 的博客-CSDN博客_selenium 反爬虫

selenium自动化测试时chrome浏览器为什么会自动关闭? - 知乎

  开发测试 最新文章
pytest系列——allure之生成测试报告(Wind
某大厂软件测试岗一面笔试题+二面问答题面试
iperf 学习笔记
关于Python中使用selenium八大定位方法
【软件测试】为什么提升不了?8年测试总结再
软件测试复习
PHP笔记-Smarty模板引擎的使用
C++Test使用入门
【Java】单元测试
Net core 3.x 获取客户端地址
上一篇文章      下一篇文章      查看所有文章
加:2021-09-18 10:30:21  更:2021-09-18 10:31:26 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/18 0:45:30-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码