我们在登录界面,输入用户名和密码之后,点击提交按钮, 浏览器会向服务器发送一个post请求, 该请求的表单数据中就包含我们输入的用户名密码等信息, 有一些做了加密的网站还可能包含一些类似 _token,的数据信息,对于这样的网站我们只需要构造表单数据, 然后向服务器发送post请求就可以实现模拟登陆了, 但是有一些做了验证码的网站, 我们就不能靠这种方法登陆了, 我们要借助selenium, 打码平台, 来帮助我们识别验证码,进行模拟登陆, 如12306网站的登录
登录的难点在于验证码的识别:
识别验证码的步骤:
-
- 用selenium访问登录界面,待页面加载完成后, 截取整张页面
- 用selenium查找标签的方法, 找到验证码图片标签, 这个标签有两个属性, location(图片左上角坐标), size(图片长和宽), 构造一个rangle()
- 用PIL的Image.open() 打开图片, 调用crop(rangle)方法, 将验证码图片从整张图片上截取下来,
- 将验证码图片发送给超级鹰处理,返回的就是需要点击的坐标,(相对坐标,相对于验证码图片左上角的坐标), 将返回结果修改成数组结构
- 用selenium的动作链, 实现点击操作
- 用selenium 输入用户名和密码, 点击登录
import time from PIL import Image from selenium import webdriver from chaojiying import Chaojiying_Client from selenium.webdriver import ActionChains def getCode(imgpath, imgType): chaojiying = Chaojiying_Client('xxxxxxxx', 'xxx', 'xxxxxxx') im = open(imgpath, 'rb').read() return chaojiying.PostPic(im, imgType)['pic_str'] bro = webdriver.Chrome() url = 'https://kyfw.12306.cn/otn/login/init' bro.get(url) time.sleep(5) #截取验证码图片 #截取整张页面的图片 bro.save_screenshot('main.png') #确定截取的范围 #找到验证码图片 img_ele = bro.find_element_by_xpath('//img[@class="touclick-image"]') #location表示的是验证码图片的左上角的坐标 location = img_ele.location #{'x': 256, 'y': 274} # print('location:', location) #size返回的是图片的长和宽 size = img_ele.size #{'height': 190, 'width': 293} # print('size:',size) #rangle就是制定好的截取范围 rangle = (int(location['x']), int(location['y']), int(location['x'])+int(size['width']), int(location['y'])+int(size['height'])) print(rangle) #根据制定好的范围进行截图 i = Image.open('main.png') #code_img_name 验证码图片的名称 code_img_name = 'code.png' frame = i.crop(rangle) frame.save(code_img_name) #记录: code.png就是验证码图片, main.png就是当前登录页面对应的图片 result = getCode('code.png', 9004) #返回的单组坐标数据 119,140 #返回的多组坐标数据 119,140|177,139|248,84 # 我们想要的数据结构式数组类型 [[119,140], [177,139]] all_points = [] for i in result.split('|'): all_points.append(i.split(',')) print('all_points', all_points) #基于selenium根据all_points进行定点的点击操作 for point in all_points: x = point[0] y = point[1] ActionChains(bro).move_to_element_with_offset(img_ele,int(x),int(y)).click().perform() time.sleep(0.5) bro.find_element_by_id('username').send_keys('123456787') time.sleep(2) bro.find_element_by_id('password').send_keys('asdf1234') time.sleep(2) bro.find_element_by_id('loginSub').click() time.sleep(10) bro.quit()