2.2.9 12306火车订票验证码处理
前言
在实现自动化测试时,最为困难的就是验证码处理;那么常规的验证码都进行处理和识别,那么如果是类似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 BaseClass
from Day22.get_path import get_image_path
import os
# from Day22.Code12306.Get_Code_Image import GetCodeImage
class 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 BaseClass
from selenium.webdriver.support.ui import WebDriverWait
import sys
import base64
import os
import time
from Day22.get_path import get_image_path
from Day22.Code12306.Click_Code import CickCode
from selenium.webdriver.common.action_chains import ActionChains
class 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火车订票验证码处理相关推荐
- Python自学笔记10:实操案例七(根据星座测试性格特点、模拟12306火车订票下单)
Python自学笔记10:实操案例七(根据星座测试性格特点.模拟12306火车订票下单) 网课传送门:https://www.bilibili.com/video/BV1Sw411Z779?p=157 ...
- python--根据星座测试性格特点-列表/模拟12306火车订票下单 --字典
根据星座测试性格特点---列表转成--集合 #创建星座列表 constellation=['白羊座','金牛座','双子座','巨蟹座','狮子座','处女座','天秤座','天蝎座','射手座',' ...
- 12306火车订票系统(C++)
文章目录 12306火车订票系统(C++) 注意事项: 设计思路-设计问题解决思路.系统功能规划: 具体实现---类设计.功能实现过程: 实现代码: 需要的文件: 2018212591马俊光的用户信息 ...
- 12306火车订票系统谈网站架构优化
转载于http://www.woshipm.com/it/3731.html 12306.cn网站挂了,被全国人民骂了.我这两天也在思考这个事,我想以这个事来粗略地和大家讨论一下网站性能的问题.因为仓 ...
- 12306 java_My12306-1.0 一个用java web写的仿12306火车订票系统 - 下载 - 搜珍网
压缩包 : a9179988ffca2a36aef2e95ba9105b.rar 列表 My12306-1.0/.classpath My12306-1.0/.mymetadata My12306-1 ...
- 春运指南之:12306网上订票自动登录下单攻略及相关最新软件
又是一年春运时,在外地打拼奔波的游子们又一次的踏上了回家的旅途,而对于为生活打拼的社会百姓来说,"火车票"三个字承载了太多了希望和心酸.今年购买火车票与往年相比,多了一种方式:网上 ...
- 12306网站服务器时间限制,12306网上订票时间限制
晚上12点之后可以在12306网站订购火车票吗?12306网上订票有时间限制吗?12306网上订票有哪些注意事项呢?今天小编就为大家介绍"12306网上订票时间限制"的相关信息吧. ...
- 12306网络订票系统登录提示解决方案
关于铁道部12306网络订票系统登录提示解决方案 介于2012年春运拉开帷幕,很多人选择了网络购票和电话订单,可是由于铁道部12306网络点击量过大,好多人根本无法登录系统进行网购:为保障农民朋友按时 ...
- 软件工程大作业(完整详细)火车订票管理系统
目录 1.1课题背景及意义 1.2研究现状 1.2.1国内研究现状 1.2.2国外研究现状 2.1可行性研究过程 2.2项目在经济上的可行性 2.3项目在法律允许的可行性 3.1功能性需求 3.1.1 ...
- android生成车票动效,Android项目源码功能齐全的12306火车票订票系统项目
[实例简介] 本项目是一个基于安卓的12306火车票客户端项目源码,实现了早期的登录注册购票改签等功能.但是因为12306网站改版比换鞋垫还频繁,所以功能早就不能用了,不过项目提供了大部分功能的原来实 ...
最新文章
- html 跳转或打开新网页
- 勤于思考:从客户端中检测到有潜在危险的 Request.Form 值
- UVa272 - TEX Quotes(输入输出)
- 如何用行为树开发游戏AI以及任务系统?
- Jenkins发布MVC应用程序
- mysql存储过程中怎么睡几秒_MySql的逻辑架构
- servlet mysql 分页_Java基础94 分页查询(以MySQL数据库为例,Servlet技术)
- java输出回文数原代码_C++编程入门:判断回文数
- Django--4、认证系统
- NumPy下载与安装
- 前端上传组件Plupload使用指南
- 大白菜u盘装win10步骤图解
- 人月神话(12)干将莫邪
- 荣盛发展,或正在步华夏幸福后尘
- Centos7 安装Chrome浏览器
- vue核心面试题:v-for中为什么要用key
- Paddle网课小助手
- python文本情感分析:SnowNLP的应用---案例
- 你是一名【合格】前端工程师吗
- 学硕与专硕,全日制与非全日制,定向与非定向......8大考研常识,你清楚吗?