selenium实现登录百度(自动识别简单验证码)
需要做的工作
0、工程结构

1、代码:
①baidu_login.py
import re
import os
import sys
import time
import random
from selenium import webdriver
from PIL import Image, ImageEnhance
import pytesseract
from func import base642str, str2base64 def input_account(account='请传入账号参数', xpath_rule="//input[@id='TANGRAM__PSP_3__userName']"):
'''模拟输入账号
:param account: 账号
:param xpath_rule: 账号输入框的xpath定位规则
:return:
'''
input_box1 = driver.find_element_by_xpath(xpath_rule)
input_box1.send_keys(account)
time.sleep(0.5) def input_pwd(pwd, xpath_rule="//input[@id='TANGRAM__PSP_3__password']"):
'''模拟输入密码
:param account: base64后的密码
:param xpath_rule: 密码输入框的xpath定位规则
:return:
'''
input_box2 = driver.find_element_by_xpath(xpath_rule)
input_box2.clear() # 清空密码
input_box2.send_keys(base642str(pwd))
time.sleep(0.5) def input_verify_code(verify_code, xpath_rule="TANGRAM__PSP_3__verifyCode"):
'''模拟输入验证码
:param account: base64后的密码
:param xpath_rule: 密码输入框的xpath定位规则
:return:
'''
driver.find_element_by_id(xpath_rule).send_keys(verify_code.strip())
time.sleep(0.5) def identify_verify_code(rootpath, pic_name="screenImg.png"):
'''tesseract识别百度验证码
:param rootpath: 验证码图片保存的文件夹路径
:param pic_name: 验证码图片保存的文件名
:return: 识别后的验证码文本
'''
# 截图或验证码图片保存地址
screenImg = os.path.join(rootpath, pic_name)
# 浏览器页面截屏
time.sleep(3)
driver.get_screenshot_as_file(screenImg)
# 定位验证码位置及大小
location = driver.find_element_by_id('TANGRAM__PSP_3__verifyCodeImg').location
size = driver.find_element_by_id('TANGRAM__PSP_3__verifyCodeImg').size
left = location['x']
top = location['y']
right = location['x'] + size['width']
bottom = location['y'] + size['height']
# 从文件读取截图,截取验证码位置再次保存
img = Image.open(screenImg).crop((left, top, right, bottom))
img = img.convert('L') # 转换模式:L | RGB
img = ImageEnhance.Contrast(img) # 增强对比度
img = img.enhance(2.0) # 增加饱和度
img.save(screenImg)
print("图片验证码以保存:%s" % screenImg)
# 再次读取识别验证码
print("开始读取识别图片验证码:%s" % screenImg)
img = Image.open(screenImg)
verifycode = pytesseract.image_to_string(img)
print("识别结果:%s" % verifycode)
return verifycode def click_a_link(xpath_rule="//p[@id='TANGRAM__PSP_3__footerULoginBtn']"):
'''点击一个链接
:param xpath_rule: 被点击链接的xpath定位规则
:return:
'''
input_box0 = driver.find_element_by_xpath(xpath_rule)
input_box0.click() def click_a_id_link(id_rule="TANGRAM__PSP_3__verifyCodeChange"):
'''点击一个链接
:param id_rule: 被点击链接的id定位规则
:return:
'''
input_box0 = driver.find_element_by_id(id_rule)
input_box0.click() def is_need_verify_code():
'''判断是否需要验证码
:return: 需要验证码返回True,否则False
'''
imgsrc = driver.find_element_by_id("TANGRAM__PSP_3__verifyCodeImg").get_attribute('src')
if re.match(r'https://passport.baidu.com/cgi-bin/genimage.*', imgsrc):
return True
else:
return False def get_id_node_text(id_rule="TANGRAM__PSP_3__error"):
'''获取id节点提示信息
:param id_rule:id节点的id匹配规则(id属性的值)
:return:该id节点中的文本信息
'''
one_node = driver.find_element_by_id(id_rule)
text_info = one_node.text
return text_info def is_login_success():
'''判断登录是否成功
:return: 登录成功返回True,否则False
'''
current_title = driver.title.strip()
if current_title.startswith("登录"):
return False
else:
return True def deal_much_pop_up_window():
'''处理手机验证码认证反复弹窗
:return:
'''
i = 0
while True: # 处理手机验证码认证反复弹窗
try:
one3_click = driver.find_element_by_id("TANGRAM__%s__header_a" % (22 + i)) # 22+i在应对弹窗的关闭按钮id名称发生变化。
except Exception as e:
print("无需手机验证码")
break
else:
print("第 %s 次弹出安全验证,要求获取手机验证码" % (i + 1))
time.sleep(0.5)
print("1s后自动选择无需手机验证码")
time.sleep(1)
one3_click.click()
print("1s后自动点击登陆")
time.sleep(1)
click_a_link(xpath_rule="//input[@id='TANGRAM__PSP_3__submit']") # 点击登录,提交表单
time.sleep(2)
# 判断是否成功登陆
current_title = driver.title.strip()
if current_title.startswith("登录"):
print('333-登陆失败...')
time.sleep(0.5)
print('333-2秒后自动重试...')
i = i + 1
time.sleep(2)
continue
else:
print("打印标题")
print(driver.title)
print('333-登录成功...')
sys.exit() # 程序终止 def deal_a_pop_up_window(xpath_rule="//input[@id='TANGRAM__PSP_27__rebindGuideCancel']"):
'''处理一次弹窗
:param xpath_rule:处理弹窗的按钮/链接的xpath匹配规则
:return:
'''
# 判断是否需要手机号绑定确认
try:
# 绑定手机号确认
one_click = driver.find_element_by_xpath(xpath_rule)
except Exception as e:
print("无需绑定手机号确认")
else:
print("弹出了绑定手机号确认,1s后自动选择不需要")
time.sleep(1)
one_click.click() if __name__ == '__main__':
# 将mm隐匿化
# print(str2base64("123456"))
# str1_base64="MTIzNDU2"
# print(base642str(str1_base64))
# sys.exit() # 账号和密码准备
account = random.randint(0, 1000000) # 随机数字作为账号
pwd = "MTIzNDU2"
print("account: %s" % account)
# 最大登录次数
max_login = 16
# 当前目录设置为根路径
ROOT_PATH = os.getcwd()
print('000-正在启用selenium...')
# 调用环境变量指定的PhantomJS浏览器创建浏览器对象
chromedriver_exe_path = os.path.join(ROOT_PATH, "chromedriver.exe")
driver = webdriver.Chrome(chromedriver_exe_path)
print('000-启用OK') # 请求登录页面
url = 'https://passport.baidu.com/v2/?login'
print('111-selenium正在请求页面:%s' % url)
driver.get(url) # get方法请求页面,获取响应
print('111-请求OK') print("打印标题")
print(driver.title) # 点击账号和密码登录
click_a_link() print('222-selenium正在填写表单...')
time.sleep(1)
# 第一次尝试登录 # 模拟填写账号
input_account(account) # 模拟填写密码
input_pwd(pwd) # 判断是否需要验证码
is_need = is_need_verify_code()
if is_need: # 需要验证码
print("需要验证码")
# 自动识别和模拟填写验证码
code = identify_verify_code(rootpath=ROOT_PATH, pic_name="screenImg.png") # 自动识别验证码
input_verify_code(code) # 模拟填写验证码
else: # 不需要验证码
print("不需要验证码")
print('222-填写表单OK')
time.sleep(1) print('333-selenium提交表单...')
click_a_link(xpath_rule="//input[@id='TANGRAM__PSP_3__submit']") # 点击登录,提交表单
print("第 %s 次尝试登录" % 1)
time.sleep(3) # 处理反复弹窗(手机验证码):点击关闭按钮
deal_much_pop_up_window()
# 处理一次弹窗(绑定手机号确认):点击不需要修改
deal_a_pop_up_window() for login_i in range(max_login - 1):
# 判断是否登录成
is_logined = is_login_success()
if is_logined:
print("登录成功")
break
else:
print("第 %s 次登录失败,正在尝试重新登录..." % (login_i + 1))
# 第二次尝试登录
print("=>第 %s 次尝试登录" % (login_i + 2))
error_info = get_id_node_text()
if ("帐号或密码错误" in error_info) or ("用户名或密码有误"): # 第二次尝试登录2.1
print("正在尝试重新输入密码...")
# 模拟填写密码
input_pwd(pwd)
# 判断是否需要验证码
is_need = is_need_verify_code()
if is_need:
print("需要验证码")
# 点击更新验证码
click_a_id_link()
# 自动识别和模拟填写验证码
code = identify_verify_code(rootpath=ROOT_PATH, pic_name="screenImg.png") # 自动识别验证码
input_verify_code(code) # 模拟填写验证码
print("提示:验证码错误,js会使得提交无效")
else:
print("不需要验证码") elif ("验证码" in error_info): # 第二次尝试登录2.2
print("正在尝试重新输入了验证码和密码...")
time.sleep(1)
# 模拟填写密码
input_pwd(pwd)
# 点击更新验证码
click_a_id_link()
# 自动识别和模拟填写验证码
code = identify_verify_code(rootpath=ROOT_PATH, pic_name="screenImg.png") # 自动识别验证码
input_verify_code(code) # 模拟填写验证码
print("提示:验证码错误,js会使得提交无效")
time.sleep(2) else:
print("其他未知异常:登录失败")
sys.exit() # 程序终止 print('222-填写表单OK')
time.sleep(1) print('333-selenium提交表单...')
click_a_link(xpath_rule="//input[@id='TANGRAM__PSP_3__submit']") # 点击登录,提交表单
time.sleep(3) # 打印标题
print("打印标题")
print(driver.title)
time.sleep(1) # 判断是否成功登陆
is_logined = is_login_success()
if is_logined:
print('333-登录成功...')
else:
print('333-登陆失败...')
②func.py
import base64
import time def timestamp2datems(timestamp):
'''
时间戳转为日期字串,精确到ms。单位s
:param timestamp:时间戳
:return:日期字串
'''
local_time = time.localtime(timestamp)
# data_head = time.strftime("%Y-%m-%d %H:%M:%S", local_time)
data_head = time.strftime("%Y-%m-%d_%H-%M-%S", local_time)
data_secs = (timestamp - int(timestamp)) * 1000
dt_ms = "%s.%03d" % (data_head, data_secs)
# print(dt_ms)
return dt_ms def bit2humanView(bit_val):
'''
文件大小bit转为人类易读大小bit、KB、MB
:param bit_val:字节数值
:return:人类易读大小和单位
'''
is2kb = int(bit_val / 1042) # 转换为kb取整
is2mb = int(bit_val / 1024 / 1024) # 转为mb取整
is2gb = int(bit_val / 1024 / 1024 / 1024) # 转为gb取整
if is2gb is not 0:
gb_val = bit_val / 1024 / 1024 / 1024
return "%.2f GB" % gb_val
if is2mb is not 0:
mb_val = bit_val / 1024 / 1024
return "%.2f MB" % mb_val
if is2kb is not 0:
kb_val = bit_val / 1024
return "%.2f KB" % kb_val
return "%s bit" % bit_val def str2base64(pwd_decode_str):
'''
明文str转为base64密文
:param pwd_decode_str: 明文str
:return: base64密文
'''
base64_encrypt = base64.b64encode(pwd_decode_str.encode('utf-8'))
pwd_encode_str = str(base64_encrypt, 'utf-8')
return pwd_encode_str def base642str(pwd_encode_str):
'''
base64密文转为明文str
:param pwd_encode_str: base64密文
:return: 明文str
'''
base64_decrypt = base64.b64decode(pwd_encode_str.encode('utf-8'))
pwd_decode_str = str(base64_decrypt, 'utf-8')
return pwd_decode_str
③依赖包:requirements.txt
Pillow==6.0.0
pytesseract==0.2.6
selenium==3.141.0
2、selenium的相关支持:
①google浏览器;
②相应版本的浏览器驱动chromedriver.exe
http://npm.taobao.org/mirrors/chromedriver/
3、PIL安装:pip install pillow
4、图像识别工具:
①windows安装tesseract.exe
②python安装pytesseract
selenium实现登录百度(自动识别简单验证码)的更多相关文章
- 案例:selenium实现登录百度(如有验证码,需要手动输入)
func.py https://www.cnblogs.com/andy9468/p/10899508.html baidu_login.py中(如有验证码,需要手动输入) # 导入webdriver ...
- unittest—selenium自动化登录百度绕过校验
这个脚本融合了unittest的校验,以及selenium的自动化,并且通过派发cookie信息成功绕过百度的验证码,并且利用装饰器成功只打开一次浏览器 #encoding=utf-8 from se ...
- selenium webdriver 登录百度
public class BaiduTest { private WebDriver driver; private String baseUrl; private StringBuffer veri ...
- Python+Selenium+PIL+Tesseract真正自动识别验证码进行一键登录
Python 2.7 IDE Pycharm 5.0.3 Selenium:Selenium的介绍及使用,强烈推荐@ Eastmount的博客 PIL : Pillow-3.3.0-cp27-cp27 ...
- Webdriver配合Tesseract-OCR 自动识别简单的验证码
验证码: 如下,在进行自动化测试,遇到验证码的问题,一般有两种方式 1.找开发去掉验证码或者使用万能验证码 2.使用OCR自动识别 使用OCR自动化识别,一般识别率不是太高,处理一般简单验证码还是没问 ...
- 简单的行为控制管理方法,自动登录,session定时验证码过期
代码很简单 实现的方式很多,用cookies 用static 变量 file文件缓存 等等 比如 //简单行为管理,如果请求此方法次数多于5次,就显示验证码 吧当前方法的name传进来,有效时间是5分 ...
- python+selenium+chrome实现自动登录百度
#python3.4+selenium3.5+chrome版本 63.0.3239.132+chrome驱动chromedriver.exe #实现自动登录百度 from selenium impor ...
- selenium cookie 登录
前言 爬虫方向的小伙伴们都知道网页爬虫经常遇到的问题就是登录账户,有些简单的网站我们可以简单的send key来输入账户密码就可以登录,但是有很多网站需要验证码之类的就不太好用了,这时候就体现到了co ...
- ASP.NET中登录功能的简单逻辑设计
ASP.NET中登录功能的简单逻辑设计 概述 逻辑设计 ...
随机推荐
- python安装lnmp
#!/usr/bin/python # -*- coding:utf-8 -*- # 注意:本实验用root用户.已经安装python3.6.5 用pycharm运行,首先把nginx安装包放在 /u ...
- iOS-UIView的layoutSubviews和drawRect方法何时调用(转)
转自:http://jianyu996.blog.163.com/blog/static/112114555201305113018814/ 首先两个方法都是异步执行.layoutSubviews方便 ...
- linux 安装了Linux generic mysql 出错
在一次安装 Linux generic cmake 出错 提示:CMake Error: The source directory "/usr/local/src" does no ...
- 各种 Java Thread State 分析
转自:https://www.cnblogs.com/zhengyun_ustc/archive/2013/03/18/tda.html 1,线程状态为“waiting for monitor ent ...
- Java 七牛云存储与下载
七牛云的文件上传和下载(私有空间) 1.本篇博客参考网址 https://blog.csdn.net/peaceful000/article/details/53171578 https://blog ...
- 《Tsinghua os mooc》第15~16讲 处理机调度
第十五讲 处理机调度 进程调度时机 非抢占系统中,当前进程主动放弃CPU时发生调度,分为两种情况: 进程从运行状态切换到等待状态 进程被终结了 可抢占系统中,中断请求被服务例程响应完成时发生调度,也分 ...
- todo---ezmorph
todo---ezmorph
- Feign【token传递】
使用feign调用服务的时候,存在一个问题,比如当前服务调用A服务,在请求头中包含了某些特殊的字段信息,比如当前操作人的token信息,调用A的时候可以正常拿到token,然而在去调用B服务的时候,可 ...
- Spring Boot系列教程十:Spring boot集成MyBatis
一.创建项目 项目名称为 "springboot_mybatis_demo",创建过程中勾选 "Web","MyBatis" ...
- 『Python基础』第4节:基础数据类型初识
本节只是对基础数据类型做个简单介绍, 详情会在之后慢慢介绍 什么是数据类型? 我们人类可以分清数字与字符串的区别, 可是计算机不能. 虽然计算机很强大, 但在某种程度上又很傻, 除非你明确告诉它数字与 ...