[未优化整理]python3selenium模块操控FireFox火狐浏览器,用于识别验证码登录系统,自动完成观看某网站的系列视频.
一. 需要用到的模块
from selenium import webdriver # 用于操控浏览器
from PIL import Image # 用于图片截取,修改. 模块安装方法pip install pillow
import pytesseract # 用于识别验证码
import bs4 # 主要用其中的bs4.BeautifulSoup类, 用于分析网页源代码,提取出超链接地址
二. 准备工作
1. 下载geckodriver,并解压复制到python安装的目录中.此程序是火狐浏览器的驱动程序,有了它python selenium模块才能驱动浏览器做事情.
下载网址:https://github.com/mozilla/geckodriver/releases
2. 下载tesseract-ocr,并安装到操作系统中.安装完成后将该软件的安装目录添加到操作系统的环境变量中.一般安装地址是:C:\Program Files (x86)\Tesseract-OCR\,环境变量设置完后一定要重启电脑.
此软件是谷歌公司的文字识别软件,我们将它配合pytesseract模块,用于识别验证码,
下载网址:https://digi.bib.uni-mannheim.de/tesseract/
3. 安装火狐浏览器
三. 程序设计中的关键点:
1. 程序主要分为两部分,一是登录, 二是学习
2. 处理弹窗
3. 使用BeautifulSoup提取出网页上的所有课程地址, 根据网页中的'finished'区分出那些是已经学了的,哪些尚未学的.
4. 尚却错误处理功能
四. 源代码: 彩色图片优化为黑字白底图片,凸显验证码,更利于后面的文字识别
def ps_img(png_a, png_b): """ 彩色图片优化为黑字白底图片,凸显验证码,更利于后面的识别 :param png_a: 原图片 :param png_b: 优化后输出图片 :return: '彩色图片优化为黑白图片完毕,输出文件名为:%s' % png_b """ img = Image.open(png_a) # from PIL import Image imgPs = img.convert('L') threshold = 140 table = [] for i in range(256): if i < threshold: table.append(0) else: table.append(1) out = imgPs.point(table, '1') out.save(png_b) return '彩色图片优化为黑白图片完毕,输出文件名为:%s' % png_b
五. 源代码: 图片识别输出为文字
def png_to_str(png='imgCodePs.png'): """ 图片识别为文字 :param png: 图片文件名 :return: 字符串 """ imgCode = Image.open(png) # from PIL import Image time.sleep(0.5) strCode = pytesseract.image_to_string(imgCode) # import pytesseract return strCode
六. 完整未优化的源代码
# -*- coding: utf-8 -*- # programming environment:windows7_64 + python3.8.3_64 from selenium import webdriver from PIL import Image import pytesseract, time import bs4 def ps_img(png_a, png_b): """ 彩色图片优化为黑字白底图片,凸显验证码,更利于后面的识别 :param png_a: 原图片 :param png_b: 优化后输出图片 :return: '彩色图片优化为黑白图片完毕,输出文件名为:%s' % png_b """ img = Image.open(png_a) # from PIL import Image imgPs = img.convert('L') threshold = 140 table = [] for i in range(256): if i < threshold: table.append(0) else: table.append(1) out = imgPs.point(table, '1') out.save(png_b) return '彩色图片优化为黑白图片完毕,输出文件名为:%s' % png_b def png_to_str(png='imgCodePs.png'): """ 图片识别并输出为文字 :param png: 图片文件名 :return: 字符串 """ imgCode = Image.open(png) # from PIL import Image time.sleep(0.5) strCode = pytesseract.image_to_string(imgCode) # import pytesseract return strCode if __name__ == '__main__': print('江苏教师教育学习开始,先登录....') url_index = 'https://www.jste.net.cn/uids/' account = {'name': '*****', 'pwd': "********"} # 需要登录的账户 browser = webdriver.Firefox() # 驱动火狐浏览器 browser.get(url_index) # 打开指定的网页 time.sleep(2) # 用户登录环节 # 点击验证码输入框,让验证码显示或变换 browser.find_element_by_name("randomCode").click() # 找到验证码输入框 while True: """ 用户登录环节 """ time.sleep(2) # 1. 获取验证码图片 # 1.1 获取验证码图片的左上角位置值和右下角的位置 imgCode = browser.find_element_by_id('imgCode') imgCodeXY = imgCode.location # 验证码图片的左上角坐标值 imgCodeSize = imgCode.size # 验证码的长宽值 imgCodeLocation = (int(imgCodeXY['x']), int(imgCodeXY['y']), int(imgCodeXY['x']) + int(imgCodeSize['width']), int(imgCodeXY['y']) + int(imgCodeSize['height'])) # 验证码左上右下位置值 # 1.2 截图验证码图片,保存为图片 time.sleep(0.5) browser.save_screenshot('login.png') # print(imgCodeLocation) time.sleep(0.5) loginImg = Image.open('login.png') time.sleep(0.2) imgCodeImg = loginImg.crop(imgCodeLocation) time.sleep(0.2) imgCodeImg.save('imgCode.png') time.sleep(0.2) # 2. 识别验证码 # 2.1 图片优化 ps_img('imgCode.png', 'imgCodePs.png') time.sleep(0.2) # 2.2 图片识别为文字 strCode = png_to_str('imgCodePs.png') time.sleep(0.1) # print(len(strCode)) # print(strCode.isalpha()) # 2.3 清理识别的错误字符串,验证码必须为字母,其余的舍弃. strCodeList = [] for i in strCode: if i.isalpha() is True: strCodeList.append(i) strCode = ''.join(strCodeList) print(strCode, len(strCode), strCode.isalpha()) # 2.4 字母必须是5位 if len(strCode) != 5: print('验证码识别有误,将重新获取验证码,再进行识别!') # 点击验证码图片,变换验证码 browser.find_element_by_id('pwd').click() browser.find_element_by_id('randomCode').click() time.sleep(1) continue # 3. 登录验证 # 3.1 输入验证码 randomCode = browser.find_element_by_name('randomCode').send_keys(strCode) time.sleep(0.5) # 3.2 输入用户名密码 browser.find_element_by_name('loginName').send_keys(account['name']) time.sleep(0.1) browser.find_element_by_name('pwd').send_keys(account['pwd']) time.sleep(0.1) # 3.3 点击登录 browser.find_element_by_class_name('Button').click() time.sleep(2) # 3.4 判断登录是否成功 url_ok = 'https://www.jste.net.cn/train/credit_hour/index.jsp' if browser.current_url == url_ok: print('登录成功') break else: print('登录失败,重新尝试...') # 学习环节 print('进入学习环节') time.sleep(2) # 用户个人首页 browser.switch_to.frame('mainFrame') # 切换到页面中的第二个框架 study_list = [] # 存储用户需要学习的课程网址 url_front = 'https://www.jste.net.cn/lfv5/learnContentLib/studentMain.action' # 课程网址的前半部分 # 点击进入学习,弹出"已经为您自动跳转到上次学习的章节" browser.find_element_by_link_text('开始学习').click() # 点击"开始学习"进入根目录 time.sleep(5) # 处理弹出窗口 first_handle = browser.current_window_handle handles = browser.window_handles for i in handles: if i != first_handle: print('处理我要从头学习弹窗') browser.close() # 关闭当前窗口 browser.switch_to.window(i) # 切换到弹出窗口 browser.find_element_by_link_text('我要从头学习').click() # 进入根目录 time.sleep(2) while True: time.sleep(1) html = browser.page_source # 获取当前页面的html网页源代码 soup = bs4.BeautifulSoup(html, 'html.parser') courseAllHtml = soup.select('.item') # 筛选html,获取所有课程的html代码 for courseHtml in courseAllHtml: if 'finished' not in str(courseHtml): # 获取未完成的课程html的str类型,并检查是否包含完成标志. study_list.append(courseHtml.get('href')) # 将未完成的课程链接加入到列表中 # 遍历课程 for link in study_list: browser.get(url_front + link) # 打开课程页面 print('打开课程页面') time.sleep(1) browser.find_elements_by_class_name('left0')[0].click() # 点击打开2.视频资源 print('打开2.视频资源页面') time.sleep(5) html = browser.page_source # 获取当前页面的html网页源代码 soup = bs4.BeautifulSoup(html, 'html.parser') videoAllHtml = soup.select('.item') # 筛选html,获取所有视频链接的html代码<a>标签 time.sleep(0.1) # 遍历课程下的视频 for videoHtml in videoAllHtml: print(str(videoHtml)) if 'finished' not in str(videoHtml): videoHtml.get('href') browser.get(url_front + videoHtml.get('href')) print('打开视频播放页面') time.sleep(60) while True: time.sleep(10) html = browser.page_source # 获取当前页面的html网页源代码 if '本项学习时间已满' in str(html): # 检查视频播放页面中是否有 本项学习时间已满 文字提示 print('单个视频观看结束') # 单个视频观看结束 browser.find_element_by_class_name('back').click() # 点击右上角返回按钮 print('点击返回上级,返回2.视频资源页面') time.sleep(2) break else: print('当前视频尚未播放结束')
七. 谷歌浏览器各版本驱动下载:
http://npm.taobao.org/mirrors/chromedriver/