有了之前的基础理论,就可以付诸实践啦
典型案例是央行征信报告系统的官网,年初在登陆页面加入了安全控件
并且只可以通过IE浏览器登陆

其中的密码输入框就是安全性更高的控件输入,由于我的浏览器已经安装过控件了,所以在密码输入未知显示的是控件框,仔细对比登陆名的dom框,还是可以看出区别的
1. 准备
需要一台windwos电脑,带IE浏览器,进入央行征信登陆页面:
https://ipcrs.pbccrc.org.cn/
安装好输入框控件
python环境的话,安装selenium包,配好iedriver,这里的操作网上教程一大堆,略过
2. 登陆分析

抓包分析,可以找到登陆入口
输入登陆名、输入密码、验证码,点击登陆按钮即可登陆:
这里先异步调用打码平台打码
然后selenium输入登陆名,winIO输入密码,等待打码完成输入验证码最后提交
3. 实践
我们创建一个模拟登陆类,将整套登陆操作封装一起来
初始化部分:
def __init__(self):
self.driver = webdriver.Ie()
self.coo = {}
self.captch = ''
self.event = Event()
driver变量用表示浏览器实例
coo变量:登陆成功的cookie
captch:验证码
基础设施:
验证码用打码平台的,控件输入密码使用之前准备好的winIO输入
其中打平台的打码时间不太稳定,我们采用线程异步的方式打码
from threading import Thread, Event
简单介绍下Event,这个对象是一个线程安全的事件信号,调用打码平台的时候先调用Event.set()方法,在其他线程同步完成系列操作之后可以调用Event.wait(time)方法,等待time时间,这里给打码平台设置5s等待时间,超时打码未完成则认作打码失败,更多进程线程介绍点这里:http://kaito-kidd.com/2018/05/11/python-advance-process-thread/
def async_ocr(self):
t = Thread(target=self.ocr)
t.setDaemon(True)
t.start()
def ocr(self):
#调用打码方法
rst = TesFunc2(self.img)
self.captch = rst
self.event.set()
winIO的包装:
之前介绍了winIO:https://www.jianshu.com/p/40a9de88153f
把输入密码的api进一步封装到类中:
def passwd(self, pwd):
for i in pwd:
input_key(i)
time.sleep(0.1)
主体登陆逻辑
1.请求登陆接口:
def start(self):
self.driver.get('https://ipcrs.pbccrc.org.cn/page/login/loginreg.jsp')
img = 'pictures/{}.png'.format(time.time())
self.driver.save_screenshot(img)
element = self.driver.find_element_by_xpath('//img[@class="yzm_img"]')
left = element.location['x']
top = element.location['y']
right = element.location['x'] + element.size['width']
bottom = element.location['y'] + element.size['height']
im = Image.open(img)
im = im.crop((left + 23, top + 1, right, bottom))
im.save(img)
self.img = img
# self.hand = self.driver.current_window_handle
self.captch = ''
该方法的作用是请求登陆页面,截取验证码保存为bytes类型,后面调用打码平台,打码
截屏用的selenium的diver对象的方法,抠图需要用到pillow库,导入:
from PIL import Image
其中的im.crop方法四个参数是验证码的像素点,浏览器可能略有误差,调整了一下左侧向右偏移了20多像素
2.输入登陆信息:
def form_submit_control(self, username, pwd):
# 异步打码
self.async_ocr()
time.sleep(0.1)
self.passwd(pwd)
name = self.driver.find_element_by_xpath('//input[@id="loginname"]')
name.send_keys(username)
img = self.driver.find_element_by_xpath('//input[@id="_@IMGRC@_"]')
# 等待打码时间通知
try:
self.event.wait(5)
except:
pass
if not self.captch:
return '打码平台异常'
img.send_keys(self.captch)
submit = self.driver.find_element_by_xpath('//input[@type="submit"]')
submit.click()
""""此处处理登陆后续操作..."""
整体的登陆逻辑就完成了