最近学校要填写对于老师的评教,不填写的就无法进行下周的选课∑^)/
我这么懒,自然不想一个一个点进去填写,想到最近在学爬虫,干脆写一个爬虫帮我弄算了
╭~~~╮
(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很多时候什么都识别不出来,也不知道出了什么问题