最近学校要填写对于老师的评教,不填写的就无法进行下周的选课∑^)/
我这么懒,自然不想一个一个点进去填写,想到最近在学爬虫,干脆写一个爬虫帮我弄算了
╭~~~╮
(o~.~o)
首先打开我们学校的信息门户:http://my.hfut.edu.cn/(仅限校园网)
可以看到我们学校的北门\(0^◇^0)/
可以看出来,用户名和密码还是很好填的,这个验证码就很麻烦了......
我选择的方法是,直接保存屏幕截图,然后利用定位元素位置定量裁剪图片,然后利用图像识别识别图中验证码, 当然,直接选图片自然是不行,要对图片先进行处理,这里,我选择的是对图像进行灰度处理,并且去除噪点,需要注意的是,很多情况下,验证码是错的,所以需要手动输入
def convert(im): #先将图片进行灰度处理,也就是处理成单色,然后进行下一步单色对比 imgrey = im.convert(‘L‘) #去除图片噪点,170是经过多次调整后,去除噪点的最佳值 ‘‘‘ 其实就是对已处理的灰度图片,中被认为可能形成验证码字符的像素进行阀值设定, 如果阀值等于170,我就认为是形成验证码字符串的所需像素,然后将其添加进一个空table中, 最后通过im.point将使用table拼成一个新验证码图片 ‘‘‘ threshold = 170 table = [] for i in range(256): if i < threshold: table.append(0) else: table.append(1) #使用table(是上面生成好的)生成图片 out = imgrey.point(table,‘1‘) out.save( ‘2222.jpeg‘,‘jpeg‘) #读取处理好的图片的路径 # a = pic_path + ‘/‘ + ‘cjb‘ + str(threshold) + ‘.jpeg‘ img3 = Image.open(‘2222.jpeg‘, ‘r‘) # 将图片中的像素点识别成字符串(图片中的像素点如果没有处理好, # 可能在识别过程中会有误差,如多个字符少个字符,或者识别错误等) vcode = pytesseract.image_to_string(img3) print(vcode) # 此句也是测试结果时使用的 return vcode#此句才是将被破解的验证码字符串返回给需要的代码的
def Verification_code(): browser.save_screenshot(‘e://aa.png‘) imgelement = browser.find_element_by_xpath(‘//*[@id="captchaImg"]‘) # 定位验证码 location = imgelement.location # 获取验证码x,y轴坐标 size = imgelement.size # 获取验证码的长宽 rangle = (int(location[‘x‘] + 230), int(location[‘y‘] + 70), int(location[‘x‘] + size[‘width‘] + 245), int(location[‘y‘] + size[‘height‘] + 80)) # 写成我们需要截取的位置坐标 i = Image.open("e://aa.png") # 打开截图 frame4 = i.crop(rangle) # 使用Image的crop函数,从截图中再次截取我们需要的区域 frame4.save(‘0000.png‘) im = Image.open(‘0000.png‘).convert(‘L‘) pytesseract.pytesseract.tesseract_cmd = ‘C:\/Program Files (x86)\/Tesseract-OCR\/tesseract.exe‘ text1 = pytesseract.image_to_string(im) print(text1) text1 = pytesseract.image_to_string(im) print(text1) text1 = pytesseract.image_to_string(im) print(text1) text1 = pytesseract.image_to_string(im) print(text1) text1 = pytesseract.image_to_string(im) print(text1) text2 = convert(im) if len(text1) == 4: if len(text2) == 4: text = text1 else: if len(text2) ==4: text = text2 else: text = text1 return text
def log_in(): browser.get(url) input_user = wait( EC.presence_of_element_located((By.CSS_SELECTOR, ‘#username‘)) ) input_pw = wait( EC.presence_of_element_located((By.CSS_SELECTOR, ‘#password‘)) ) input_yanzhengma = wait( EC.presence_of_element_located((By.CSS_SELECTOR, ‘#code‘)) ) confirm = input(‘是否使用默认账户登录:‘) if confirm == ‘y‘: user = ‘2016214224‘ pw = ‘leiheng.1.1‘ else: user = input("账号:") pw = input("密码:") input_user.send_keys(user) input_pw.send_keys(pw) text = Verification_code() if text: print(‘验证码获取成功...\n验证码为:‘, text) input_yanzhengma.send_keys(text) else: print(‘验证码获取失败‘) if ‘0000.png‘: print(‘验证码保存成功...‘) text = input(‘请查看图片,输入验证码:‘) input_yanzhengma.send_keys(text) Confirm_login() def Repeat_verification(chance): if not chance: print(‘验证码错误,请手动输入验证码...‘) if ‘0000.png‘: print(‘验证码已保存...‘) text = input(‘请查看图片,输入验证码:‘) input_yanzhengma = wait( EC.presence_of_element_located((By.CSS_SELECTOR, ‘#code‘)) ) input_yanzhengma.clear() input_yanzhengma.send_keys(text) Confirm_login() def Confirm_login(): submit = wait( EC.element_to_be_clickable((By.CSS_SELECTOR, ‘#loginForm > table:nth-child(1) > tbody > tr:nth-child(3) > td > input[type="submit"]:nth-child(3)‘)) ) submit.click() try: new_button = wait( EC.element_to_be_clickable((By.CSS_SELECTOR, ‘#pf7802 > div > div.portletContent > table > tbody > tr:nth-child(2) > td:nth-child(1) > table > tbody > tr:nth-child(1) > td > a > img‘)) ) print(‘登录成功...‘) return 1 except TimeoutException: Repeat_verification(0) return 0
之后,就可以选择继续填写老师的评测了,当然,中间需要跳转几个网页。
def questionnaire(): new_button = wait( EC.element_to_be_clickable((By.CSS_SELECTOR, ‘#pf7802 > div > div.portletContent > table > tbody > tr:nth-child(2) > td:nth-child(1) > table > tbody > tr:nth-child(1) > td > a > img‘)) ) new_button.click() windows = browser.window_handles browser.close() browser.switch_to.window(windows[-1]) new_test = wait( EC.element_to_be_clickable((By.CSS_SELECTOR, ‘#e-op-area > div > div > div > div > div:nth-child(7) > div‘)) ) new_test.click() windows = browser.window_handles browser.close() browser.switch_to.window(windows[-1]) time.sleep(2) html = browser.page_source partten = re.compile(‘<a name=.*?url="(.*?)">(.*?)</a>‘, re.S) items = re.findall(partten, html) for item in items: teacher = item[1] print(‘正在进行‘+teacher+‘老师的测评‘) next_page = ‘http://jxglstu.hfut.edu.cn‘ + item[0] url = next_page browser.get(url) blist = [‘达到目标‘, ‘匹配‘, ‘契合‘, ‘认真‘, ‘能充分利用教材设计教学方案,并做好教学预设。‘, ‘能合理地利用现代教育技术手段。‘, ‘能合理地运用多种教学方法。‘, ‘能根据教学设计组织教学活动,并对学生进行有效引导 。‘ , ‘学生积极参与教学活动,较好地掌握所学知识和技能,并对其发展产生积极影响。‘, ‘能根据学生对课堂内容的掌握情况,适当拓展与延伸专业知识,激发学生学习兴趣,并拓展学生的学习视野。‘] for i in range(10): b = wait( EC.element_to_be_clickable((By.CSS_SELECTOR, ‘[value="‘ + blist[i] + ‘"]‘)) ) b.click() print(teacher+‘老师的评测以结束,进行下一位老师的评测‘) submit_test = wait( EC.element_to_be_clickable((By.CSS_SELECTOR, ‘#save-button‘)) ) time.sleep(2) submit_test.click() time.sleep(1)
到这里基本上已经结束了。
有几点需要总结:
1)从登陆模块来看,目前无法解决如何将密码输入时进行隐藏,
2)从验证码模块来看,目前图像识别还是很难
3)从转跳网页来看,要注意将操作从先前的窗口转移到下一个窗口,不然很容易导致查询网页元素时找不到而心烦意乱
4)从页面加载来看,要注意合理选择页面加载的标志性元素,保证页面中需要的元素以及全部加载成功
5)从查找元素来看,要注意对延迟性操作的延迟时间的控制,注意网速,并且合理在BeautifulSoup以及PyQuery和正则表达式中合理选择。
6)从对元素的操作来看,注意元素的操作方式是否正确
7)从窗口的关闭来说,browser.close()仅仅关闭一个窗口;而browser.quit()关闭的是由这个browser所加载的各个进程,注意结尾使用
8)有一个很尴尬的情况,图像识别中pytesseract.image_to_string很多时候什么都识别不出来,也不知道出了什么问题