selenium模拟登录12306官网 +超级鹰识别验证码

前言

超级鹰开发文档: http://www.chaojiying.com/api.html
我这里用的python,点击下载就好了。

一、通过selenium自动登录12306官网

from selenium import webdriver
from time import sleep
from PIL import Image
from selenium.webdriver import ActionChains
import requests
from hashlib import md5
#超级鹰第三方接口
class Chaojiying_Client(object):

    def __init__(self, username, password, soft_id):
        self.username = username
        password =  password.encode('utf8')
        self.password = md5(password).hexdigest()
        self.soft_id = soft_id
        self.base_params = {
            'user': self.username,
            'pass2': self.password,
            'softid': self.soft_id,
        }
        self.headers = {
            'Connection': 'Keep-Alive',
            'User-Agent': 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)',
        }

    def PostPic(self, im, codetype):
        """
        im: 图片字节
        codetype: 题目类型 参考 http://www.chaojiying.com/price.html
        """
        params = {
            'codetype': codetype,
        }
        params.update(self.base_params)
        files = {'userfile': ('ccc.jpg', im)}
        r = requests.post('http://upload.chaojiying.net/Upload/Processing.php', data=params, files=files, headers=self.headers)
        return r.json()

    def ReportError(self, im_id):
        """
        im_id:报错题目的图片ID
        """
        params = {
            'id': im_id,
        }
        params.update(self.base_params)
        r = requests.post('http://upload.chaojiying.net/Upload/ReportError.php', data=params, headers=self.headers)
        return r.json()

driver=webdriver.Chrome(executable_path=r'./chromedriver')
driver.maximize_window() #全屏
## 打开12306官网
driver.get('https://kyfw.12306.cn/otn/resources/login.html')
#选择账号登陆并点击
driver.find_element_by_xpath('/html/body/div[2]/div[2]/ul/li[2]/a').click()
sleep(2)
#截屏整张图,后续找到验证码的坐标,做裁剪
driver.save_screenshot('./12306.png')

#确定验证码图片的左上角和右下角的坐标(裁剪区域就确定了)
code_img_ele = driver.find_element_by_xpath('//*[@id="J-loginImg"]')
location = code_img_ele.location #验证码图片左上角的坐标{'x': 766, 'y': 284}
size=code_img_ele.size #验证码标签对应的长和宽  #{'height': 188, 'width': 300}
print(location,size)
#左上角和右下角的坐标,元组的形式存储,后续截取 电脑分辨率默认为125%
rangle = (
    int(location['x'])*1.25,int(location['y'])*1.25,int((location['x']+size['width'])*1.25),int((location['y']+size['height'])*1.25),
)
print(rangle)
code_img_name ='./code.png'
#裁剪验证码并保存
img = Image.open('./12306.png')
frame=img.crop(rangle)
frame.save(code_img_name)

#超级鹰识别
chaojiying = Chaojiying_Client('账号', '密码', '904142')  # 用户中心>>软件ID 生成一个替换 904142
im = open('./code.png', 'rb').read()  # 本地图片文件路径 来替换 a.jpg 有时WIN系统须要//
# 返回验证码需点击的坐标对象
result = chaojiying.PostPic(im, 9004)['pic_str']  #验证码类型  官方网站>>价格体系 3.4+版 print 后要加()

# 创建坐标数据结构
all_list = []  #[[140,166],[59,173],]
if '|' in result: #140,166|59,173
    list_1 = result.split('|')
    count_1 = len(list_1)
    for i in range(count_1):
        xy_list = []
        x = int(list_1[i].split(',')[0])
        y = int(list_1[i].split(',')[1])
        xy_list.append(x)
        xy_list.append(y)
        all_list.append(xy_list)
else:
    x = int(result.split(',')[0])
    y = int(result.split(',')[1])
    xy_list = []
    xy_list.append(x)
    xy_list.append(y)
    all_list.append(xy_list)

#动作链作移动定位时,需要等比缩小25%即可
for list in all_list:
    x = list[0]*0.85
    y = list[1]*0.85
    # 实例化动作链并立即执行移动操作
    action=ActionChains(driver)
    #以code_img_ele验证码标签为参照物
    action.move_to_element_with_offset(code_img_ele,x,y).click().perform()
    sleep(0.5)
# 获取到输入框 用户名
driver.find_element_by_id('J-userName').send_keys('xxx@qq.com')
# 获取到输入框 密码
driver.find_element_by_id('J-password').send_keys('xxx...')
sleep(1)
# 点击登录
driver.find_element_by_id('J-login').click()
sleep(2)
#下载界面
page_text = driver.page_source
with open("12306.html", "w", encoding="utf-8") as fp:
    fp.write(page_text)

sleep(3)
driver.quit()

二、python+selenium+Chromedriver使用location定位元素坐标偏差的问题

使用xpath定位元素,用.location获取坐标值,截取网页截图的一部分出现偏差。

之所以会出现这个坐标偏差是因为windows系统下电脑设置的显示缩放比例造成的(一般默认是125%),location获取的坐标是按显示100%时得到的坐标,而截图所使用的坐标却是需要根据显示缩放比例缩放后对应的图片所确定的,因此就出现了偏差。
解决这个问题有三种方法:
1.修改电脑显示设置为100%。这是最简单的方法;
2.缩放截取到的页面图片,即将截图的size缩放为宽和高都除以缩放比例后的大小(坐标大小*1.25);
3.修改Image.crop的参数,将参数元组的四个值都乘以缩放比例。
上面代码的实现是用的方法 ② ③

# 以当前电脑125%缩放比为例
rangle = (int(location_position["x"]*1.25), int(location_position["y"]*1.25),
          int((location_position["x"] + img_size["width"])*1.25),
          int((location_position["y"] + img_size["height"])*1.25))

# 动作链作移动定位时,需要等比缩小25%即可
for lis in all_list:
    x = lis[0]*0.85
    y = lis[1]*0.85
    # 实例化动作链并立即执行移动操作
    ActionChains(dri).move_to_element_with_offset(code_img, x, y).click().perform()
    sleep(0.5)

参考:
https://blog.csdn.net/weixin_43751840/article/details/88423031
https://www.cnblogs.com/WiseAdministrator/articles/11318122.html

posted @ 2020-03-23 18:02  hanfe1  阅读(676)  评论(0编辑  收藏  举报