利用selenium+chrome模拟登陆合工大信息门户并进行自动填写测评

最近学校要填写对于老师的评教,不填写的就无法进行下周的选课∑^)/

我这么懒,自然不想一个一个点进去填写,想到最近在学爬虫,干脆写一个爬虫帮我弄算了

╭~~~╮
(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很多时候什么都识别不出来,也不知道出了什么问题

 

posted @ 2017-12-23 11:33  慵懒的仙人掌  阅读(2000)  评论(0编辑  收藏  举报