前言

在实现自动化测试时,最为困难的就是验证码处理;那么常规的验证码都进行处理和识别,那么如果是类似12306等图片识别的验证码的话如何实现?那么今天小编就给大家分析下12306验证码如何实现自动化。

获取12306验证码图片

按照常规思路无非两种,将截取的验证码图片发送给第三方服务器,然后通过第三方服务器进行识别后将结果进行返回;要么就是自己通过机器识别的方式不断进行学习,写大量的识别库然后完成识别操作;第二种方式耗时耗力,显然不可取,所以大部分都是选择第三方服务器进行完成;

验证码图片的获取可以通过传统的Pillow模块完成图片的截取操作;但是此种方式会出现失真(是图片的质量下降,模糊),所以此处为了提高其图片的质量,可以直接获取图片的文件流对象,然后自己将文件流对象转换成图片的过程;

通过分析系12306页面,使用元素定位发现验证码的src属性是可以直接获取对应图片通过base64加密的数据流,如果能够将此数据流转换成字节流,然后保存成图片不就获取到原始图片了。

那么获取到src属性的结果值则可以通过下面代码完成:

  self.get_code_elment=WebDriverWait(self.get_driver,5).until(lambda driver:driver.find_element_by_id("J-loginImg"))  get_src=self.get_code_elment.get_attribute("src")

但是得到的结果是base64编码数据流,所以可以通过base模块完成数据流转换成字节流,定义一个方法封装后即可获取到对应验证码图片

​​​​​​​

    def  get_code_image(self):        self.get_driver.find_element_by_class_name("login-hd-account").click()        try:            self.get_code_elment=WebDriverWait(self.get_driver,5).until(lambda driver:driver.find_element_by_id("J-loginImg"))            #此处src数据加载问题            time.sleep(3)            get_src=self.get_code_elment.get_attribute("src")            #得到base64格式编码数据            get_base64=get_src.split(",")[-1]            #获取到bytes对象,文件、图像实际都是基于byte流            get_byte=base64.b64decode(get_base64)            print(self.image_path)            with open(self.image_path,mode="wb") as fp:                #既可以实现以二进制流的形式读和写两种操作                fp.write(get_byte)        except:            print(sys.exc_info())

获取到验证码图片后,并将其保存到本地,最后将验证码图片发送到第三方服务器进行识别,此处使用的第三方服务器地址是:

http://littlebigluo.qicp.net:47720/访问后发现可以上传一张图片,然后会自动识别并返回对应验证码的图序号;后续只需要根据返回的图需要进行完成对应图的点击操作即可;(此处使用接口完成更加,但是此时为web自动化,所以使用了新创建一个浏览器对象进行操作),具体代码如下:

#-*- coding:utf-8 -*-##-------------------------------------------------------------------------#ProjectName:       Python2020#FileName:          Click_Code.py#Author:            mutou#Date:              2020/6/16 22:43#Description:#--------------------------------------------------------------------------from Day18.BaseModule.Base_Class import BaseClassfrom Day22.get_path import get_image_pathimport os# from Day22.Code12306.Get_Code_Image import GetCodeImageclass CickCode(BaseClass):    def __init__(self,url,browserType):        super(CickCode, self).__init__(url,browserType)
    #声明一个方法上传图片pic_xxfile    def  up_image(self,image_path):        self.get_driver.find_element_by_name("pic_xxfile").send_keys(image_path)        self.get_driver.find_element_by_xpath("/html/body/form/input[2]").click()        #识别后需要将识别的结果进行返回并获取        get_result=self.get_driver.find_element_by_xpath("/html/body/p[1]/font/font/b").text        #如果返回的是多个值的话,则值与值之间使用空格隔开        get_result_list=get_result.split(" ")        #获取结果后,此页面可以进行关闭        self.get_driver.close()        return get_result_list
if __name__ == '__main__':    get = GetCodeImage("https://kyfw.12306.cn/otn/resources/login.html", "Chrome","code.jpg")    get.get_code_image()    click=CickCode("http://littlebigluo.qicp.net:47720/","Chrome")    print(click.up_image(get.image_path))

获取到验证码的返回结果后,最后完成点击操作即可,此时点击需要注意以下几个问题:

第一:每个小图对应的坐标点

第二:如果存在多个图的话,则如何实现连续操作

同样还是通过鼠标定位发现验证码图片的长和高大小如下:其中长:300  高:188

那么如果每个小图取中间点的话,则可以把整个大验证码图片的中心作为原点,然后其他所有点全部相对该点进行偏移;最后可得到八个点:如下分析图:

然后由于浏览器的坐标并不是等价于数学的二维坐标方向,浏览器中是以左上角为原点,那么此时高就是y轴,从上往下的过程,宽还是x轴,所以上图分析的坐标点需要完成对称象限的操作;即结果为:

[-110,-30],[-40,-30],[40,-30],[110,-30],[-110,50],[-40,50],[40,50],[110,50]

最后可以通过鼠标模块中的move_by_offset方法完成点击操作;具体实现部分代码如下:​​​​​​​

#-*- coding:utf-8 -*-##-------------------------------------------------------------------------#ProjectName:       Python2020#FileName:          Get_Code_Image.py#Author:            mutou#Date:              2020/6/16 20:53#Description:获取12306验证码图片#--------------------------------------------------------------------------from Day18.BaseModule.Base_Class import BaseClassfrom selenium.webdriver.support.ui import WebDriverWaitimport sysimport base64import osimport timefrom Day22.get_path import get_image_pathfrom Day22.Code12306.Click_Code import CickCodefrom selenium.webdriver.common.action_chains import ActionChainsclass  GetCodeImage(BaseClass):    def __init__(self,url,browserType,image_name):        super().__init__(url,browserType)        self.image_name=image_name        self.image_path=os.path.join(get_image_path,image_name)        self.location=[[-110,-30],[-40,-30],[40,-30],[110,-30],[-110,50],[-40,50],[40,50],[110,50]]
    #获取12306验证码图片;最简单的方式就是通过Pillow模块完成验证码图片从首页中进行截取出来,直接截取出来的图片会影响图片的质量    #将图片变得模糊;如何提高图片质量的问题:图片都是以二进制数据进行传输的,如果能够直接获取图片的原二进制数据的话, 然后将二进制数据转写成    #一张图片,那么中间就不会发生质量问题;    def  get_code_image(self):        self.get_driver.find_element_by_class_name("login-hd-account").click()        try:            self.get_code_elment=WebDriverWait(self.get_driver,5).until(lambda driver:driver.find_element_by_id("J-loginImg"))            #此处src数据加载问题            time.sleep(3)            get_src=self.get_code_elment.get_attribute("src")            #得到base64格式编码数据            get_base64=get_src.split(",")[-1]            #获取到bytes对象,文件、图像实际都是基于byte流            get_byte=base64.b64decode(get_base64)            print(self.image_path)            with open(self.image_path,mode="wb") as fp:                #既可以实现以二进制流的形式读和写两种操作                fp.write(get_byte)        except:            print(sys.exc_info())
    #定义一个方法完成验证码的点击操作    def click_code(self,server_path,type):        #获取到第三方返回的结果        get_result_list=CickCode(server_path,type).up_image(self.image_path)        print(get_result_list)        #提取鼠标创建的对象        action=ActionChains(self.get_driver)        #遍历对应的图        for i in get_result_list:            #因为可以根据鼠标移动到指定的坐标点完成点击操作            #创建鼠标对象;此处的i表示的是第几幅图,而下面传入location中表示的是索引            get_value=self.location[int(i)-1]            #设定的坐标点是相对真个验证码图片而言,所以可以先讲鼠标对象移动到当前验证码元素对象上,然后实现偏移点击坐标点            action.move_to_element(self.get_code_elment).move_by_offset(get_value[0],get_value[1]).click()            #上面此种实现相当于完成每一次点击都重新创建一个鼠标对象。在程序开发中,实际是尽量的减少循环中创建对象;            #如果将鼠标创建对象提取的话,则必须将执行的动作于整个循环完毕后执行,否则在循环中有可能整个动作就已经被执行,则后续动作无法执行;        action.perform()if __name__ == '__main__':    get=GetCodeImage("https://kyfw.12306.cn/otn/resources/login.html","Chrome","code.jpg")   # print(get.image_path)    get.get_code_image()    get.click_code("http://littlebigluo.qicp.net:47720/","Chrome")#注意:两个模块的相互引用容易造成模块初始化错误

如果需要获取整个所有的完整项目代码的话,则回复【12306】即可

2.2.9 12306火车订票验证码处理相关推荐

  1. Python自学笔记10:实操案例七(根据星座测试性格特点、模拟12306火车订票下单)

    Python自学笔记10:实操案例七(根据星座测试性格特点.模拟12306火车订票下单) 网课传送门:https://www.bilibili.com/video/BV1Sw411Z779?p=157 ...

  2. python--根据星座测试性格特点-列表/模拟12306火车订票下单 --字典

    根据星座测试性格特点---列表转成--集合 #创建星座列表 constellation=['白羊座','金牛座','双子座','巨蟹座','狮子座','处女座','天秤座','天蝎座','射手座',' ...

  3. 12306火车订票系统(C++)

    文章目录 12306火车订票系统(C++) 注意事项: 设计思路-设计问题解决思路.系统功能规划: 具体实现---类设计.功能实现过程: 实现代码: 需要的文件: 2018212591马俊光的用户信息 ...

  4. 12306火车订票系统谈网站架构优化

    转载于http://www.woshipm.com/it/3731.html 12306.cn网站挂了,被全国人民骂了.我这两天也在思考这个事,我想以这个事来粗略地和大家讨论一下网站性能的问题.因为仓 ...

  5. 12306 java_My12306-1.0 一个用java web写的仿12306火车订票系统 - 下载 - 搜珍网

    压缩包 : a9179988ffca2a36aef2e95ba9105b.rar 列表 My12306-1.0/.classpath My12306-1.0/.mymetadata My12306-1 ...

  6. 春运指南之:12306网上订票自动登录下单攻略及相关最新软件

    又是一年春运时,在外地打拼奔波的游子们又一次的踏上了回家的旅途,而对于为生活打拼的社会百姓来说,"火车票"三个字承载了太多了希望和心酸.今年购买火车票与往年相比,多了一种方式:网上 ...

  7. 12306网站服务器时间限制,12306网上订票时间限制

    晚上12点之后可以在12306网站订购火车票吗?12306网上订票有时间限制吗?12306网上订票有哪些注意事项呢?今天小编就为大家介绍"12306网上订票时间限制"的相关信息吧. ...

  8. 12306网络订票系统登录提示解决方案

    关于铁道部12306网络订票系统登录提示解决方案 介于2012年春运拉开帷幕,很多人选择了网络购票和电话订单,可是由于铁道部12306网络点击量过大,好多人根本无法登录系统进行网购:为保障农民朋友按时 ...

  9. 软件工程大作业(完整详细)火车订票管理系统

    目录 1.1课题背景及意义 1.2研究现状 1.2.1国内研究现状 1.2.2国外研究现状 2.1可行性研究过程 2.2项目在经济上的可行性 2.3项目在法律允许的可行性 3.1功能性需求 3.1.1 ...

  10. android生成车票动效,Android项目源码功能齐全的12306火车票订票系统项目

    [实例简介] 本项目是一个基于安卓的12306火车票客户端项目源码,实现了早期的登录注册购票改签等功能.但是因为12306网站改版比换鞋垫还频繁,所以功能早就不能用了,不过项目提供了大部分功能的原来实 ...

最新文章

  1. html 跳转或打开新网页
  2. 勤于思考:从客户端中检测到有潜在危险的 Request.Form 值
  3. UVa272 - TEX Quotes(输入输出)
  4. 如何用行为树开发游戏AI以及任务系统?
  5. Jenkins发布MVC应用程序
  6. mysql存储过程中怎么睡几秒_MySql的逻辑架构
  7. servlet mysql 分页_Java基础94 分页查询(以MySQL数据库为例,Servlet技术)
  8. java输出回文数原代码_C++编程入门:判断回文数
  9. Django--4、认证系统
  10. NumPy下载与安装
  11. 前端上传组件Plupload使用指南
  12. 大白菜u盘装win10步骤图解
  13. 人月神话(12)干将莫邪
  14. 荣盛发展,或正在步华夏幸福后尘
  15. Centos7 安装Chrome浏览器
  16. vue核心面试题:v-for中为什么要用key
  17. Paddle网课小助手
  18. python文本情感分析:SnowNLP的应用---案例
  19. 你是一名【合格】前端工程师吗
  20. 学硕与专硕,全日制与非全日制,定向与非定向......8大考研常识,你清楚吗?

热门文章

  1. 微信存储空间占用问题
  2. 小刘的http状态码整理
  3. 火狐浏览器书签无法删除解决方案
  4. 利用Word实现交叉引用或引用尾注添加参考文献图解
  5. 《史蒂夫·乔布斯传》——童年篇有感
  6. 新时期文学专题研究【1】
  7. 初中几何知识复习,已知直角三角形角度和邻边长求对边长
  8. Unity在运行时使用FBX SDK的API
  9. 矩阵标准型的系数是特征值吗_数据分析基础:特征值和特征向量
  10. android hid 触摸屏驱动,针对USB接口触摸屏HID免驱触摸屏配置方法