python
一、前言
本文通过selenium工具实现工作所用网站的自动登录,下图为网站登录界面。
1、运行环境
操作系统:Windows10
python版本:python3.7
2、需要的python第三方库
1、selenium
安装:
pip install selenium
selenium是ThoughtWorks提供的一个强大的基于浏览器的开源自动化测试工具。支持的浏览器包括IE、Chrome和Firefox等。
另外还需要下载浏览器驱动,我这里用的是Google浏览器驱动。
Google浏览器驱动:官网链接
选择适配的浏览器版本和Windows系统,然后将下载得到的exe文件放到python的安装目录下。
2、baidu_api
安装:
pip install baidu_api
baidu_api是百度文字识别的OCR(Optical Character Recognition,光学字符识别),很多人可能会用tesseract库,但以测试的效果来看,百度的API识别效果更好。了解此库大家可以看官方文档。百度OCR-API官方文档
3、pillow
安装:
pip install pillow
pillow库是python最常用的第三方图像处理库
二、代码实现
1、导入第三方库
from selenium import webdriver
from PIL import Image
from aip import AipOcr
2、验证码的获取与处理
在进行验证码的获取之前,需要先实例化一个browser对象,代码如下:
browser = webdriver.Chrome() # 实例化对象
获取验证码的方法是通过实例化后的browser对象的查找元素方法的得到验证码元素并截图。下为网站源代码的验证码标签。
代码如下:
url = 'http://120.77.44.123/Login/Login.aspx?title=exit&recode=1'
browser.get(url)
png = browser.find_element_by_id('captcha_img') # 查找验证码元素
png.screenshot('capt.png') # 对验证码进行截图并保存
这是获得的验证码图片:
为了提高验证码的识别率,我们需要用pillow库对验证码进行图像处理。
处理方法如下:
1、先将图像转换成灰度模式
2、通过对阈值的调整使得多余的噪点消失
img = Image.open('capt.png')
img = img.convert('L') # P模式转换为L模式(灰度模式默认阈值127)
count = 165 # 设定阈值
table = []
for i in range(256):if i < count:table.append(0)else:table.append(1)img = img.point(table, '1')
img.save('captcha1.png') # 保存处理后的验证码
处理效果如下:
可以通多对阈值的调整使得程序获得更高的识别率。
3、验证码的识别
处理完验证码后现在我们可以对其进行识别,调用baidu_api的通用文字识别接口,官方文档上有详细的调用方法,每日可以免费使用5000次,这个数字也够挥霍了。
# 识别码
APP_ID = '*** '
API_KEY = '***'
SECRET_KEY = '***'
# 初始化对象
client = AipOcr(APP_ID, API_KEY, SECRET_KEY)
# 读取图片
def get_file_content(file_path):with open(file_path, 'rb') as f:return f.read()image = get_file_content('captcha.png')
# 定义参数变量
options = {'language_type': 'ENG', } # 识别语言类型,默认为'CHN_ENG'中英文混合
# 调用通用文字识别
result = client.basicGeneral(image, options) # 高精度接口 basicAccurate
for word in result['words_result']:captcha = (word['words'])print('识别结果:' + captcha)return captcha
这是打印出的识别结果:
整体来看,识别效果还可以,当然这个验证码本身就不难。
4、自动键入信息并登录
这里用到的依然是browser对象的元素查找方法,代码如下:
browser.find_element_by_id('j_username').send_keys('***') # 找到账号框并输入账号
browser.find_element_by_id('j_password').send_keys('***') # 找到密码框并输入密码
browser.find_element_by_id('j_captcha').send_keys(captcha) # 找到验证码框并输入验证码
browser.find_element_by_id('login_ok').click() # 找到登陆按钮并点击
代码执行到这里,也就实现了网站的自动登录,下面是程序的完整代码。
三、完整代码
from selenium import webdriver
from PIL import Image
from aip import AipOcr# 验证码的获取和处理
def get_captcha():# 获取验证码图片url = 'http://120.77.44.123/Login/Login.aspx?title=exit&recode=1'browser.get(url)png = browser.find_element_by_id('captcha_img')png.screenshot('capt.png') # 将图片截屏并保存# 处理验证码img = Image.open('capt.png')img = img.convert('L') # P模式转换为L模式(灰度模式默认阈值127)count = 160 # 设定阈值table = []for i in range(256):if i < count:table.append(0)else:table.append(1)img = img.point(table, '1')img.save('captcha.png') # 保存处理后的验证码# 验证码的识别
def discern_captcha():# 识别码APP_ID = '*** 'API_KEY = '***'SECRET_KEY = '***'# 初始化对象client = AipOcr(APP_ID, API_KEY, SECRET_KEY)# 读取图片def get_file_content(file_path):with open(file_path, 'rb') as f:return f.read()image = get_file_content('captcha.png')# 定义参数变量options = {'language_type': 'ENG', } # 识别语言类型,默认为'CHN_ENG'中英文混合# 调用通用文字识别result = client.basicGeneral(image, options) # 高精度接口 basicAccuratefor word in result['words_result']:captcha = (word['words'])print('识别结果:' + captcha)return captcha# 登录网页
def login(captcha):browser.find_element_by_id('j_username').send_keys('***') # 找到账号框并输入账号browser.find_element_by_id('j_password').send_keys('***') # 找到密码框并输入密码browser.find_element_by_id('j_captcha').send_keys(captcha) # 找到验证码框并输入验证码browser.find_element_by_id('login_ok').click() # 找到登陆按钮并点击def get_file():browser.find_element_by_xpath('/html/body/header/div/nav/ul/li[6]/a').click() # 找到文件按钮并点击if __name__ == '__main__':browser = webdriver.Chrome() # 实例化对象get_captcha()captcha = discern_captcha()login(captcha)get_file()
HTML
先看一下最终效果,登陆和注册
背景图片:
附源码:
login.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 |
|
register.html
1 <!DOCTYPE html>2 <html lang="en">3 4 <head>5 <meta charset="UTF-8">6 <title>register</title>7 <style>8 * {9 margin: 0;10 padding: 0;11 }12 13 html {14 height: 100%;15 width: 100%;16 overflow: hidden;17 margin: 0;18 padding: 0;19 background: url(Desert.jpg) no-repeat 0px 0px;20 background-repeat: no-repeat;21 background-size: 100% 100%;22 -moz-background-size: 100% 100%;23 }24 25 body {26 display: flex;27 align-items: center;28 justify-content: center;29 height: 100%;30 }31 32 #loginDiv {33 width: 37%;34 display: flex;35 justify-content: center;36 align-items: center;37 height: 650px;38 background-color: rgba(75, 81, 95, 0.3);39 box-shadow: 7px 7px 17px rgba(52, 56, 66, 0.5);40 border-radius: 5px;41 }42 43 #name_trip {44 margin-left: 50px;45 color: red;46 }47 48 p,49 .sexDiv {50 margin-top: 10px;51 margin-left: 20px;52 color: azure;53 }54 55 .sexDiv>input,56 .hobby>input {57 width: 30px;58 height: 17px;59 }60 61 input,62 select {63 margin-left: 15px;64 border-radius: 5px;65 border-style: hidden;66 height: 30px;67 width: 140px;68 background-color: rgba(216, 191, 216, 0.5);69 outline: none;70 color: #f0edf3;71 padding-left: 10px;72 }73 74 .button {75 border-color: cornsilk;76 background-color: rgba(100, 149, 237, .7);77 color: aliceblue;78 border-style: hidden;79 border-radius: 5px;80 width: 100px;81 height: 31px;82 font-size: 16px;83 }84 85 .introduce {86 margin-left: 110px;87 }88 89 .introduce>textarea {90 background-color: rgba(216, 191, 216, 0.5);91 border-style: hidden;92 outline: none;93 border-radius: 5px;94 }95 96 h1 {97 text-align: center;98 margin-bottom: 20px;99 margin-top: 20px; 100 color: #f0edf3; 101 } 102 103 b { 104 margin-left: 50px; 105 color: #FFEB3B; 106 font-size: 10px; 107 font-weight: initial; 108 } 109 </style> 110 </head> 111 112 <body> 113 <div id="loginDiv"> 114 <form action=""> 115 <h1>REGESTER</h1> 116 <p>用户姓名:<input id="userNname" type="text" autofocus required><label id="name_trip"></label></p> 117 118 <p>用户密码:<input id="password" type="password" required><label id="password_trip"></label></p> 119 120 <p>确认密码:<input id="surePassword" type="password" required><label id="surePassword_trip"></label></p> 121 122 <p> 123 用户类型: 124 <select name="type" id="userType"> 125 <option value="0">请选择</option> 126 <option value="1">普通类型</option> 127 <option value="2">VIP类型</option> 128 </select> 129 <label id="type_trip"></label> 130 </p> 131 132 <div class="sexDiv"> 133 用户性别: 134 <input class="userSex" name="sex" value="boy" type="radio">男 135 <input class="userSex" name="sex" value="girl" type="radio">女 136 <label id="sex_trip"></label> 137 </div> 138 139 <p> 140 出生日期: 141 <input id="birthday" type="date"> 142 <label id="birthday_trip"></label> 143 </p> 144 145 <p class="hobby"> 146 兴趣爱好: 147 <input type="checkbox" name="hobby" value="read">阅读 148 <input type="checkbox" name="hobby" value="music">音乐 149 <input type="checkbox" name="hobby" value="sport">运动 150 <label id="hobby_trip"></label> 151 </p> 152 153 <p> 154 电子邮件: 155 <input id="email" type="email" required> 156 <label id="emil_trip"></label> 157 </p> 158 159 160 <p> 自我介绍:</p> 161 <div class="introduce"> 162 <textarea name="introduce" cols="30" id="introduceText" required rows="10"></textarea> 163 <label id="introduce_trip"></label> 164 </div> 165 166 <p style="text-align: center;"> 167 <input type="submit" class="button" οnblur="checkForm()" οnclick="return submitT()" value="提交"> 168 <input type="reset" class="button" value="重置"> 169 </p> 170 </form> 171 </div> 172 173 </body> 174 <script type="text/javascript"> 175 function trip(obj, trip) { 176 document.getElementById(obj).innerHTML = "<b>" + trip + "</b>"; 177 } 178 179 function checkSex() { 180 var sexNum = document.getElementsByName("sex"); 181 var sex = ""; 182 for (let i = 0; i < sexNum.length; ++i) { 183 if (sexNum[i].checked) { 184 sex = sexNum[i]; 185 } 186 187 } 188 if (sex == "") { 189 trip("sex_trip", "ERROR!!"); 190 return false; 191 } else { 192 trip("sex_trip", "OK!!"); 193 } 194 } 195 196 function checkHobby() { 197 var hobbyNum = document.getElementsByName("hobby"); 198 var hobby = ""; 199 for (let i = 0; i < hobbyNum.length; ++i) { 200 if (hobbyNum[i].checked) { 201 hobby = hobbyNum[i]; 202 } 203 } 204 if (hobby == "") { 205 trip("hobby_trip", "ERROR!!"); 206 return false; 207 } else { 208 trip("hobby_trip", "OK!!"); 209 210 } 211 } 212 213 function checkSelect() { 214 var myselect = document.getElementById("userType"); 215 var index = myselect.selectedIndex; 216 var checkValue = myselect.options[index].value; 217 if (checkValue == 0) { 218 trip("type_trip", "请选择!!"); 219 return false; 220 } else { 221 trip("type_trip", "OK!!"); 222 } 223 } 224 225 function checkForm() { 226 checkSelect(); 227 checkHobby(); 228 checkSex(); 229 230 var trip = document.getElementsByName("em"); 231 var tripV = trip.innerHTML(); 232 //获取用户名输入项 233 var userNname = document.getElementById("userNname"); 234 var uName = userNname.value; 235 if (uName.length < 1 || uName.length > 10) { 236 trip("name_trip", "账号长度为1-10位!!"); 237 return false; 238 } else { 239 trip("name_trip", "OK!!"); 240 241 } 242 243 //密码长度大于6 和确认必须一致 244 var password = document.getElementById("password"); 245 var userPass = password.value; 246 if (userPass.length < 6) { 247 trip("password_trip", "密码要>6位!!"); 248 return false; 249 } else { 250 trip("password_trip", "OK!!"); 251 } 252 253 //获取确认密码框的值 var 254 var surePassword = document.getElementById("surePassword"); 255 var surePass = surePassword.value; 256 if (userPass != surePass) { 257 trip("surePassword_trip", "两次密码不一致!!"); 258 return false; 259 } 260 261 //校验邮箱:/^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+(\.[a-zA-Z0-9_-])+/ 262 var inputEmail = document.getElementById("email"); 263 var uEmail = inputEmail.value; 264 if (!/^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+(\.[a-zA-Z0-9_-])+/.test(uEmail)) { 265 trip("emil_trip", "邮箱不合法!!"); 266 return false; 267 } else { 268 trip("emil_trip", "OK!!"); 269 } 270 271 // 校验自我介绍 272 var introduceText = document.getElementById("introduceText"); 273 var introduce = introduceText.value; 274 if (introduce.length < 3 || uName.length > 60) { 275 trip("introduce_trip", "长度为3-50字!!"); 276 return false; 277 } else { 278 trip("introduce_trip", "OK!!"); 279 } 280 281 return true; 282 } 283 284 function submitT() { 285 if (checkForm()) { 286 return true; 287 } else { 288 return false; 289 } 290 } 291 </script> 293 </html>