selenium实现登录百度(自动识别简单验证码)

需要做的工作

0、工程结构

 

1、代码:

 ①baidu_login.py

  1 import re
  2 import os
  3 import sys
  4 import time
  5 import random
  6 from selenium import webdriver
  7 from PIL import Image, ImageEnhance
  8 import pytesseract
  9 from func import base642str, str2base64
 10 
 11 
 12 def input_account(account='请传入账号参数', xpath_rule="//input[@id='TANGRAM__PSP_3__userName']"):
 13     '''模拟输入账号
 14     :param account: 账号
 15     :param xpath_rule: 账号输入框的xpath定位规则
 16     :return:
 17     '''
 18     input_box1 = driver.find_element_by_xpath(xpath_rule)
 19     input_box1.send_keys(account)
 20     time.sleep(0.5)
 21 
 22 
 23 def input_pwd(pwd, xpath_rule="//input[@id='TANGRAM__PSP_3__password']"):
 24     '''模拟输入密码
 25     :param account: base64后的密码
 26     :param xpath_rule: 密码输入框的xpath定位规则
 27     :return:
 28     '''
 29     input_box2 = driver.find_element_by_xpath(xpath_rule)
 30     input_box2.clear()  # 清空密码
 31     input_box2.send_keys(base642str(pwd))
 32     time.sleep(0.5)
 33 
 34 
 35 def input_verify_code(verify_code, xpath_rule="TANGRAM__PSP_3__verifyCode"):
 36     '''模拟输入验证码
 37     :param account: base64后的密码
 38     :param xpath_rule: 密码输入框的xpath定位规则
 39     :return:
 40     '''
 41     driver.find_element_by_id(xpath_rule).send_keys(verify_code.strip())
 42     time.sleep(0.5)
 43 
 44 
 45 def identify_verify_code(rootpath, pic_name="screenImg.png"):
 46     '''tesseract识别百度验证码
 47     :param rootpath: 验证码图片保存的文件夹路径
 48     :param pic_name: 验证码图片保存的文件名
 49     :return: 识别后的验证码文本
 50     '''
 51     # 截图或验证码图片保存地址
 52     screenImg = os.path.join(rootpath, pic_name)
 53     # 浏览器页面截屏
 54     time.sleep(3)
 55     driver.get_screenshot_as_file(screenImg)
 56     # 定位验证码位置及大小
 57     location = driver.find_element_by_id('TANGRAM__PSP_3__verifyCodeImg').location
 58     size = driver.find_element_by_id('TANGRAM__PSP_3__verifyCodeImg').size
 59     left = location['x']
 60     top = location['y']
 61     right = location['x'] + size['width']
 62     bottom = location['y'] + size['height']
 63     # 从文件读取截图,截取验证码位置再次保存
 64     img = Image.open(screenImg).crop((left, top, right, bottom))
 65     img = img.convert('L')  # 转换模式:L | RGB
 66     img = ImageEnhance.Contrast(img)  # 增强对比度
 67     img = img.enhance(2.0)  # 增加饱和度
 68     img.save(screenImg)
 69     print("图片验证码以保存:%s" % screenImg)
 70     # 再次读取识别验证码
 71     print("开始读取识别图片验证码:%s" % screenImg)
 72     img = Image.open(screenImg)
 73     verifycode = pytesseract.image_to_string(img)
 74     print("识别结果:%s" % verifycode)
 75     return verifycode
 76 
 77 
 78 def click_a_link(xpath_rule="//p[@id='TANGRAM__PSP_3__footerULoginBtn']"):
 79     '''点击一个链接
 80     :param xpath_rule: 被点击链接的xpath定位规则
 81     :return:
 82     '''
 83     input_box0 = driver.find_element_by_xpath(xpath_rule)
 84     input_box0.click()
 85 
 86 
 87 def click_a_id_link(id_rule="TANGRAM__PSP_3__verifyCodeChange"):
 88     '''点击一个链接
 89     :param id_rule: 被点击链接的id定位规则
 90     :return:
 91     '''
 92     input_box0 = driver.find_element_by_id(id_rule)
 93     input_box0.click()
 94 
 95 
 96 def is_need_verify_code():
 97     '''判断是否需要验证码
 98     :return: 需要验证码返回True,否则False
 99     '''
100     imgsrc = driver.find_element_by_id("TANGRAM__PSP_3__verifyCodeImg").get_attribute('src')
101     if re.match(r'https://passport.baidu.com/cgi-bin/genimage.*', imgsrc):
102         return True
103     else:
104         return False
105 
106 
107 def get_id_node_text(id_rule="TANGRAM__PSP_3__error"):
108     '''获取id节点提示信息
109     :param id_rule:id节点的id匹配规则(id属性的值)
110     :return:该id节点中的文本信息
111     '''
112     one_node = driver.find_element_by_id(id_rule)
113     text_info = one_node.text
114     return text_info
115 
116 
117 def is_login_success():
118     '''判断登录是否成功
119     :return: 登录成功返回True,否则False
120     '''
121     current_title = driver.title.strip()
122     if current_title.startswith("登录"):
123         return False
124     else:
125         return True
126 
127 
128 def deal_much_pop_up_window():
129     '''处理手机验证码认证反复弹窗
130     :return:
131     '''
132     i = 0
133     while True:  # 处理手机验证码认证反复弹窗
134         try:
135             one3_click = driver.find_element_by_id("TANGRAM__%s__header_a" % (22 + i))  # 22+i在应对弹窗的关闭按钮id名称发生变化。
136         except Exception as e:
137             print("无需手机验证码")
138             break
139         else:
140             print("第 %s 次弹出安全验证,要求获取手机验证码" % (i + 1))
141             time.sleep(0.5)
142             print("1s后自动选择无需手机验证码")
143             time.sleep(1)
144             one3_click.click()
145             print("1s后自动点击登陆")
146             time.sleep(1)
147             click_a_link(xpath_rule="//input[@id='TANGRAM__PSP_3__submit']")  # 点击登录,提交表单
148             time.sleep(2)
149             # 判断是否成功登陆
150             current_title = driver.title.strip()
151             if current_title.startswith("登录"):
152                 print('333-登陆失败...')
153                 time.sleep(0.5)
154                 print('333-2秒后自动重试...')
155                 i = i + 1
156                 time.sleep(2)
157                 continue
158             else:
159                 print("打印标题")
160                 print(driver.title)
161                 print('333-登录成功...')
162                 sys.exit()  # 程序终止
163 
164 
165 def deal_a_pop_up_window(xpath_rule="//input[@id='TANGRAM__PSP_27__rebindGuideCancel']"):
166     '''处理一次弹窗
167     :param xpath_rule:处理弹窗的按钮/链接的xpath匹配规则
168     :return:
169     '''
170     # 判断是否需要手机号绑定确认
171     try:
172         # 绑定手机号确认
173         one_click = driver.find_element_by_xpath(xpath_rule)
174     except Exception as e:
175         print("无需绑定手机号确认")
176     else:
177         print("弹出了绑定手机号确认,1s后自动选择不需要")
178         time.sleep(1)
179         one_click.click()
180 
181 
182 if __name__ == '__main__':
183     # 将mm隐匿化
184     # print(str2base64("123456"))
185     # str1_base64="MTIzNDU2"
186     # print(base642str(str1_base64))
187     # sys.exit()
188 
189     # 账号和密码准备
190     account = random.randint(0, 1000000)  # 随机数字作为账号
191     pwd = "MTIzNDU2"
192     print("account: %s" % account)
193     # 最大登录次数
194     max_login = 16
195     # 当前目录设置为根路径
196     ROOT_PATH = os.getcwd()
197     print('000-正在启用selenium...')
198     # 调用环境变量指定的PhantomJS浏览器创建浏览器对象
199     chromedriver_exe_path = os.path.join(ROOT_PATH, "chromedriver.exe")
200     driver = webdriver.Chrome(chromedriver_exe_path)
201     print('000-启用OK')
202 
203     # 请求登录页面
204     url = 'https://passport.baidu.com/v2/?login'
205     print('111-selenium正在请求页面:%s' % url)
206     driver.get(url)  # get方法请求页面,获取响应
207     print('111-请求OK')
208 
209     print("打印标题")
210     print(driver.title)
211 
212     # 点击账号和密码登录
213     click_a_link()
214 
215     print('222-selenium正在填写表单...')
216     time.sleep(1)
217     # 第一次尝试登录
218 
219     # 模拟填写账号
220     input_account(account)
221 
222     # 模拟填写密码
223     input_pwd(pwd)
224 
225     # 判断是否需要验证码
226     is_need = is_need_verify_code()
227     if is_need:  # 需要验证码
228         print("需要验证码")
229         # 自动识别和模拟填写验证码
230         code = identify_verify_code(rootpath=ROOT_PATH, pic_name="screenImg.png")  # 自动识别验证码
231         input_verify_code(code)  # 模拟填写验证码
232     else:  # 不需要验证码
233         print("不需要验证码")
234         print('222-填写表单OK')
235         time.sleep(1)
236 
237     print('333-selenium提交表单...')
238     click_a_link(xpath_rule="//input[@id='TANGRAM__PSP_3__submit']")  # 点击登录,提交表单
239     print("第 %s 次尝试登录" % 1)
240     time.sleep(3)
241 
242     # 处理反复弹窗(手机验证码):点击关闭按钮
243     deal_much_pop_up_window()
244     # 处理一次弹窗(绑定手机号确认):点击不需要修改
245     deal_a_pop_up_window()
246 
247     for login_i in range(max_login - 1):
248         # 判断是否登录成
249         is_logined = is_login_success()
250         if is_logined:
251             print("登录成功")
252             break
253         else:
254             print("第 %s 次登录失败,正在尝试重新登录..." % (login_i + 1))
255             # 第二次尝试登录
256             print("=>第 %s 次尝试登录" % (login_i + 2))
257             error_info = get_id_node_text()
258             if ("帐号或密码错误" in error_info) or ("用户名或密码有误"):  # 第二次尝试登录2.1
259                 print("正在尝试重新输入密码...")
260                 # 模拟填写密码
261                 input_pwd(pwd)
262                 # 判断是否需要验证码
263                 is_need = is_need_verify_code()
264                 if is_need:
265                     print("需要验证码")
266                     # 点击更新验证码
267                     click_a_id_link()
268                     # 自动识别和模拟填写验证码
269                     code = identify_verify_code(rootpath=ROOT_PATH, pic_name="screenImg.png")  # 自动识别验证码
270                     input_verify_code(code)  # 模拟填写验证码
271                     print("提示:验证码错误,js会使得提交无效")
272                 else:
273                     print("不需要验证码")
274 
275             elif ("验证码" in error_info):  # 第二次尝试登录2.2
276                 print("正在尝试重新输入了验证码和密码...")
277                 time.sleep(1)
278                 # 模拟填写密码
279                 input_pwd(pwd)
280                 # 点击更新验证码
281                 click_a_id_link()
282                 # 自动识别和模拟填写验证码
283                 code = identify_verify_code(rootpath=ROOT_PATH, pic_name="screenImg.png")  # 自动识别验证码
284                 input_verify_code(code)  # 模拟填写验证码
285                 print("提示:验证码错误,js会使得提交无效")
286                 time.sleep(2)
287 
288             else:
289                 print("其他未知异常:登录失败")
290                 sys.exit()  # 程序终止
291 
292             print('222-填写表单OK')
293             time.sleep(1)
294 
295             print('333-selenium提交表单...')
296             click_a_link(xpath_rule="//input[@id='TANGRAM__PSP_3__submit']")  # 点击登录,提交表单
297             time.sleep(3)
298 
299     # 打印标题
300     print("打印标题")
301     print(driver.title)
302     time.sleep(1)
303 
304     # 判断是否成功登陆
305     is_logined = is_login_success()
306     if is_logined:
307         print('333-登录成功...')
308     else:
309         print('333-登陆失败...')
View Code

②func.py

import base64
import timedef 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)) * 1000dt_ms = "%s.%03d" % (data_head, data_secs)# print(dt_ms)return dt_msdef 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 / 1024return "%.2f GB" % gb_valif is2mb is not 0:mb_val = bit_val / 1024 / 1024return "%.2f MB" % mb_valif is2kb is not 0:kb_val = bit_val / 1024return "%.2f KB" % kb_valreturn "%s bit" % bit_valdef 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_strdef 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

 

3、PIL安装:pip  install  pillow

 

4、图像识别工具:

①windows安装tesseract.exe 

②python安装pytesseract

 

转载于:https://www.cnblogs.com/andy9468/p/10907741.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/350474.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

为什么猫王不应该访问Java

最近,我参与了一个关于Java的Optional类型系统的漫长的Twitter讨论 ,该系统区分可空类型和非可空类型以及Elvis运算符 ,该运算符允许选择空值安全的成员。 后者被认为是简洁的null处理的杀手级功能,对此我强烈不同意。 我对此的看…

python a and b_python-尽管Numpy建议a.b,为什么a.dot(b)比a @ b更...

根据question的答案,也根据numpy的答案,与a.dot(b)相比,二维数组的矩阵乘法最好通过a b或numpy.matmul(a,b)完成.If both a and b are 2-D arrays, it is matrix multiplication, but usingmatmul or a b is preferred.我做了以下基准测试,发现相反的结果.问题:我的…

Mysql高可用集群-解决MMM单点故障

目录 一.理论概述组件介绍三.部署四.测试五.总结preface: MMM架构相比于MHA来说各方面都逊色不少,写这篇案例也算是整理下思路吧. 一.理论概述 MMM(Master-Master replication Manager for MySQL) 是一套支持双主日常管理的脚本程序,使用Perl语言开发,主要用来监控和管理MySQL双…

vector元素的读取

1通过下标&#xff1a; int a[6] { 1,2,3,4,5,6 }; vector<int> b(a, a 4); for (int i 0; i < b.size() - 1; i) cout << b[i] << " "; 2通过迭代器 int a[6] { 1,2,3,4,5,6 }; vector<int> b(a, a 4); for (vector<int>:…

vector 中的元素去重

#include<iostream> #include<vector> #include<algorithm> using namespace std; int main() { cout << "********************一维向量*************************" << endl; vector<int> a; for (int i 0; i < 6; i) …

tcp的3次握手4次挥手

转载于:https://www.cnblogs.com/georgexu/p/10909808.html

python 如何定义字典_python dict如何定义

1.字典的定义字典的格式&#xff1a;字典名 {key1:value1, key2:value2,...}字典是无序的&#xff0c;是可变的数据类型字典的key不能是可变的数据类型(列表 字典)字典的key是不能重复的&#xff0c;但value可以例&#xff1a;my_dict {"name": "小明", …

MS SQL JSON类型type

在MS SQL Server 2016&#xff0c;已经支持JSON处理。 执行下面代码&#xff0c;将获取ms sql server对象类型以及其说明: IF OBJECT_ID(tempdb.dbo.#json_type) IS NOT NULL DROP TABLE #json_typeCREATE TABLE #json_type ( [type] TINYINT,[data_type] NVARCHAR(30) ) IN…

Eigen(8)实例最小二乘法

用Eigen库解Axb线性方程&#xff0c;使用最小二乘法 #include <iostream>#include <Eigen/Dense>using namespace std;using namespace Eigen;int main(){//对方程AxbMatrixXf A MatrixXf::Random(3, 2);std::cout << "Here is the matrix A:\n"…

java 和javafx_JavaFX 2 XYCharts和Java 7功能

java 和javafx我最喜欢的JavaFX 2功能之一是它在javafx.scene.chart包中提供的标准图表。 该软件包提供了几种不同类型的现成图表。 除其中之一&#xff08; PieChart &#xff09;外&#xff0c;所有其他均为“ 2轴图”&#xff08; XYChart的特定实现&#xff09;。 在本文中…

python语句分为什么语句_在python中如何分句

在处理文本时&#xff0c;会遇到需要将文本以 句子 为单位进行切分(分句)的场景&#xff0c;而文本又可以分为 中文文本 和 英文文本 &#xff0c;处理的方法会略有不同。本文会介绍 Python 是如何处理 分句 的。分句的关键是找到合适的结束符号&#xff0c;比如&#xff1a;中…

Spring框架(二) ---- bean的歧义性

自动装配bean时&#xff0c;如果符合条件的bean超过一个&#xff0c;就会出现歧义性&#xff0c;抛出NoUniqueBeanDefinitionException异常&#xff0c;有如下两种方法保证bean的唯一性&#xff1a; 一、使用Primary注解标记首选bean 1.与Component注解组合使用在自动扫描的bea…

Eigen(7)Map类

这里将解释Eigen如何与原生raw C/C 数组混合编程。 1. 简介 Eigen中定义了一系列的vector和matrix&#xff0c;相比copy数据&#xff0c;更一般的方式是复用数据的内存&#xff0c;将它们转变为Eigen类型。Map类很好地实现了这个功能。 2. Map类型 Map的定义 Map<Matrix&…

从战中清理代码

从战中清除代码–验证 让我们直接从一个例子开始。 考虑一个简单的Web服务&#xff0c;该服务允许客户向商店下订单。 订单控制器的非常简化的版本可能如下所示– RestController RequestMapping(value "/",consumes MediaType.APPLICATION_JSON_VALUE,produces …

python opencv屏幕找图_使用Python+OpenCV进行图像模板匹配(Match Template)实例-找到百度首页按钮并点击...

意图&#xff1a;准备一张小图&#xff0c;在电脑屏幕上找到小图坐标&#xff0c;并点击。1 安装 opencv 和 numpy&#xff1a;pip3 install opencv-python上述命令将 opencv 和 numpy都安装了&#xff0c;可以在类似D:\Python36\Lib\site-packages目录下看到2 准备小图&…

Eigen(6)快操作

1. 块操作 块是matrix或array中的矩形子部分。 2. 使用块 函数.block()&#xff0c;有两种形式 operation 构建一个动态尺寸的block 构建一个固定尺寸的block 起点(i,j)块大小(p,q) .block(i,j,p,q) .block< p,q >(i,j) Eigen中&#xff0c;索引从0开始。 两个版本…

11.【原创】chrom文件上传后,手动释放内存

最近在用google chrom测试大文件上传功能&#xff0c;上传的文件为4GB左右的。但是试了几次之后突然发现&#xff0c;我C盘的内存由原先的剩余的30多GB变为了15GB左右&#xff0c;猜想是chrom文件上传之后并没有把读取出的文件进行清理。网上找了很久也没有找到类似解决方法。于…

mapreduce排序算法_MapReduce算法–二级排序

mapreduce排序算法我们将继续执行有关实现MapReduce算法的系列文章&#xff0c;该系列可在使用MapReduce进行数据密集型文本处理中找到。 本系列的其他文章&#xff1a; 使用MapReduce进行数据密集型文本处理 使用MapReduce进行数据密集型文本处理-本地聚合第二部分 使用Had…

数据图表与分析图_几种可视化数据分析图表的使用

图表简洁大方、一目了然&#xff0c;利用图表工具就能轻松实现&#xff0c;是数据分析中常采用的方式。今天利用在雀书无代码平台搭建的图表来介绍几种常见数据分析图表的使用。1. 柱状图柱状图可以显示一段时间内的数据变化或显示各项之间的比较情况&#xff0c;主要使用颜色进…

java打包exe

配置如下&#xff1a; 1&#xff0c;复制运行环境jre&#xff1b; 2&#xff0c;复制项目配置文件config; 3&#xff0c;复制项目运行的lib包&#xff1b; 4&#xff0c;编写清单文件&#xff0c;放到系统目录&#xff1b; 5&#xff0c;将项目打包成xxx.jar&#xff0c;放入到…