当前位置: 移动技术网 > IT编程>网页制作>HTML > JNU教务系统一键成绩查询

JNU教务系统一键成绩查询

2020年07月22日  | 移动技术网IT编程  | 我要评论

本文使用到的主要第三方库:selenium
本文主要使用第三方API:腾讯通用文字识别API

由于最近出于出成绩时期,每天都会查一下成绩,学校的教务系统cookie不操作一段时间会过期,又要重新登入.需要输入验证码.就感觉挺麻烦的,所以就搞了个自动查询吧.

待解决问题:

  • 如何访问学校教务系统网站,获取数据.一开始我是想采用http协议get,post直接获取html数据的…不过实在有点懒了,还是直接用之前就用过的selenium库吧.

  • 验证码问题:验证码的问题,我前前后后想了好几种解决策略吧,首先是尝试了COOKIE,想试试免登入,不过失败了.然后就是尝试绕过验证码,事实证明,虽然教务系统的服务器是土豆,不过也没那么好破解.第三条路就是图像识别了.关于图像识别我尝试了两种方案:

  • 首先是pytesseract.我的理解就是一个图像识别引擎,不过直接用的识别率真的太菜了.然后我尝试对学校验证码降噪,一开始是二值化后,去掉细线.不过虽然学校验证码看着挺草率的两条线,搞起来挺要命的,有粗有细.不太好根据线的宽度进行降噪.我又想到了根据颜色来降噪.因为线是单独的一种颜色,取色器取色,再遍历像素,如果是线的颜色,就改为背景色.即使这样,识别度还是不高.在我以为要失败的时候.

  • 想起了QQ截图自带的文字识别功能,一试…流批!没处理过的验证码都识别出来了,然后我就立刻去找有没有开放API,还真有.那验证码的问题也解决了.

学校验证码示例

首先是对网站进行操作的相关源码

from selenium import webdriver
from tencentapi import api
from selenium.webdriver.support.ui import Select

#隐藏了浏览器窗口,以及selenium的日志
chrome_options = webdriver.ChromeOptions()
chrome_options.add_argument('headless')
chrome_options.add_experimental_option('excludeSwitches', ['enable-logging'])
driver = webdriver.Chrome(chrome_options=chrome_options)

driver.get("https://webvpn.jnu.edu.cn/")  # 地址栏里输入网址
driver.find_element_by_id('user_login').send_keys("")#账号
driver.find_element_by_id('user_password').send_keys('')#密码
driver.find_element_by_name('commit').click()

Flag=True
#验证码识别率不是百分百,不成功就再试一次
while(Flag):
    try:
        driver.get("https://jwxt-443.webvpn.jnu.edu.cn/")  # 地址栏里输入网址
        driver.find_element_by_id('txtYHBS').send_keys("")#账号
        driver.find_element_by_id('txtYHMM').send_keys('')#密码
        img = driver.find_element_by_xpath('/html/body/form/table/tbody/tr/td/table/tbody/tr/td/table/tbody/tr[2]/td[2]/table/tbody/tr[9]/td[3]/img')
        #我只能说,这行代码真的很厉害
        base64_data=img.screenshot_as_base64
        FJM = api(base64_data)
        driver.find_element_by_id('txtFJM').send_keys(FJM) 
        driver.find_element_by_id('btnLogin').click()
        driver.get('https://jwxt-443.webvpn.jnu.edu.cn/Secure/Cjgl/Cjgl_Cjcx_XsCxXqCj.aspx')
    except:
        pass
    else:
        break

# driver.get('https://jwxt-443.webvpn.jnu.edu.cn/Secure/Cjgl/Cjgl_Cjcx_XsCxXqCj.aspx')


s1 = Select(driver.find_element_by_id('ddListXQ'))
s1.select_by_value('下')
driver.find_element_by_id('lbtnQuery').click()

print(driver.find_element_by_id('dgrdList').text)

在中间其实会遇到一个问题,我觉得挺棘手的,就是验证码的获取问题.由于验证码的src并不是静态的,如果重新通过src获取只会获取到新的验证码图片,网上的方法都是采用截图的方法,我看网上的方法感觉很复杂,很绝望.然后随手对img元素打了个.结果索引出了screenshot方法,更流批的是,还可以as_base64,我人都傻了,只能喊句selenium流批!(后面API的调用,使用的就是图片的base64编码)

关于腾讯API的调用源码

# with open("ValidateCode.png","rb") as f:
#     # b64encode是编码,b64decode是解码
#     base64_data = base64.b64encode(f.read())
#     base64_data = str(base64_data,'utf-8')
#     # print(base64_data)
import json
from tencentcloud.common import credential
from tencentcloud.common.profile.client_profile import ClientProfile
from tencentcloud.common.profile.http_profile import HttpProfile
from tencentcloud.common.exception.tencent_cloud_sdk_exception import TencentCloudSDKException 
from tencentcloud.ocr.v20181119 import ocr_client, models
def api(base64_data): 
    base64_data = base64_data
    try: 
        cred = credential.Credential("这里是secretid", "这里是key") 
        httpProfile = HttpProfile()
        httpProfile.endpoint = "ocr.tencentcloudapi.com"

        clientProfile = ClientProfile()
        clientProfile.httpProfile = httpProfile
        client = ocr_client.OcrClient(cred, "ap-guangzhou", clientProfile) 

        req = models.EnglishOCRRequest()
        params = '{\"ImageBase64\":\"'+base64_data+'\"}'
        req.from_json_string(params)

        resp = client.EnglishOCR(req) 
        
        # print(resp.to_json_string()) 

        json1 = json.loads(resp.to_json_string())
        FJM = json1['TextDetections'][0]['DetectedText']
        # print(FJM)
    except TencentCloudSDKException as err: 
        print(err)
    return FJM

这个代码就没啥特别的了…不是简单,我也不会写,这是API的demo,原样复制…我只是加了个json操作方便读取识别结果,然后封装成函数方便调用.

腾讯文字识别API文档
登入账号获取id和key后要在这里实名注册,开通服务,每个月免费1000次识别,理论上够用

感慨:

  • 又是一篇对第三方库调用的操作…调参侠好歹还调调参呢
  • 虽然没搞啥技术,但是selenium是真滴强…现在互联网公司搞得人工智能API也是真滴强…
  • 又划水了一天
  • 还是想知道以前的公众号是怎么解决的验证码问题

下面是失败了的pytesseract尝试,也不算完全没用吧,降噪处理的话,说不定可以提高一下API的识别正确率

#coding = utf -8
from PIL import Image
import pytesseract
import cv2
import numpy as np
import matplotlib.pyplot as plt
import math
from PIL import Image,ImageEnhance,ImageFilter
from PIL import Image


color=[(255,0,0),(211,211,211)]
img = Image.open("ValidateCode.png")#读取系统的内照片
# print (img.size)#打印图片大小
# print (img.getpixel((4,4)))

width = img.size[0]#长度
height = img.size[1]#宽度
for i in range(0,width):#遍历所有长度的点
    for j in range(0,height):#遍历所有宽度的点
        data = (img.getpixel((i,j)))#打印该图片的所有点
        # print (data)#打印每个像素点的颜色RGBA的值(r,g,b,alpha)
        # print (data[0])#打印RGBA的r值
        if (data[0]==105 and data[1]==105 and data[2]==105):#RGBA的r值大于170,并且g值大于170,并且b值大于170
            count=[0,0]
            for t in range(3):
                for q in range(3):
                    if(i+t-1>=0 and j+q-1>=0 and i+t-1<width and j+q-1<height):
                        temp = img.getpixel((i+t-1,j+q-1))
                        if(temp[0]==255):
                            count[0]+=1
                        else:
                            count[1]+=1
            

            img.putpixel((i,j),color[count.index(max(count))])#则这些像素点的颜色改成大红色


img.save('1.png')

im = Image.open("1.png")
text = pytesseract.image_to_string((im))

print (text)

本文地址:https://blog.csdn.net/rglkt/article/details/107498682

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网