先看一下正方教务系统的主页面
俺们杭电人废话不多说,直接上程序
代码
import requests
from selenium import webdriver
from selenium.webdriver import ChromeOptions
import parsel
import time
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.by import By
import json
import requests
import base64
from io import BytesIO
from PIL import Image
from sys import version_info
import threading
url = 'http://jxgl.hdu.edu.cn/default.aspx'
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.9 Safari/537.36'}
def main():
# askurl(url)
# getnlink(url)
getdata()
def dri(url): #登陆页面
option = ChromeOptions() # 添加用户配置
option.add_experimental_option('excludeSwitches', ['enable-automation']) # 模拟开发者模式
driver = webdriver.Chrome(options = option)
driver.get(url)
driver.find_element_by_id('un').clear() # 清空输入框
driver.find_element_by_id('un').send_keys('18081828') # 输入学号
driver.find_element_by_id('pd').clear()
driver.find_element_by_id('pd').send_keys('Hdu1041116') # 输入密码
driver.find_element_by_id('index_login_btn').click()
return driver
def action():
driver = dri(url)
# html = driver.page_source
# data = parsel.Selector(html)
# ylink = data.xpath('//img[@src]').extract[0]
# print(ylink)
ActionChains(driver).move_to_element(driver.find_element_by_link_text("网上选课")).perform()
time.sleep(1)
driver.find_element_by_link_text(class_nature).click()
driver.switch_to_default_content()
frame = driver.find_elements_by_tag_name('iframe')[0]
driver.switch_to_frame(frame)
time.sleep(1)
# time.sleep(2)
# ActionChains(driver).click(driver.find_element_by_id("ddl_ywyl")).perform() #有无余量
# # time.sleep(1)
# driver.find_element_by_xpath('//option[@value="有"]').click()
ActionChains(driver).click(driver.find_element_by_id("ddl_kcgs")).perform()#课程性质
driver.find_element_by_xpath('//option[@value="通识选修一般课"]').click()
# ActionChains(driver).click(driver.find_element_by_id("ddl_sksj")).perform() #上课时间
# driver.find_element_by_xpath('//option[@value="周二第10,11节{第1-16周}"]').click()
driver.find_element_by_id('TextBox1').send_keys(class_name) #课程名
driver.find_element_by_id('Button2').click()
driver.find_element_by_id('kcmcGrid_ctl02_xk').click() #选择课程
time.sleep(1)
driver.find_element(By.XPATH,'//img')
driver.save_screenshot("yzm2.png")
ran = Image.open("yzm2.png")
box = (1125, 485, 1190, 525) # 获取验证码位置,自动定位不是很明白,就使用了手动定位,代表(左,上,右,下)
ran.crop(box).save("yzm3.png")
img_path = "yzm3.png"
img = Image.open(img_path)
result = base64_api(uname='shj', pwd='shj459321', img=img)
driver.find_element_by_id('txtYz').clear()
driver.find_element_by_id('txtYz').send_keys(result)
driver.find_element_by_id('Button1').click()
def getdata():
for i in range(0,5):
t = threading.Thread(target=action, name="" + str(i), args=())
t.start()
def base64_api(uname, pwd, img): #调用第三方网站的api
img = img.convert('RGB')
buffered = BytesIO()
img.save(buffered, format="JPEG")
if version_info.major >= 3:
b64 = str(base64.b64encode(buffered.getvalue()), encoding='utf-8')
else:
b64 = str(base64.b64encode(buffered.getvalue()))
data = {"username": uname, "password": pwd, "image": b64}
result = json.loads(requests.post("http://api.ttshitu.com/base64", json=data).text)
if result['success']:
return result["data"]["result"]
else:
return result["message"]
return ""
def main1():
img_path = "yzm.jpg"
img = Image.open(img_path)
result = base64_api(uname='shj', pwd='shj459321', img=img)
return result
if __name__ == '__main__':
class_nature = '通识选修课'
class_name = '澳大利亚的文化之旅'
main()
``
解释:代码其实很简单,无非就是selenium控制鼠标键盘和webdriver定位元素的一些操作,详情可以(https://blog.csdn.net/qq_32897143/article/details/80383502),要是还有不懂得可以找度娘,度娘是万能的
比较棘手的就是验证码识别的问题,本人以前也自学过机关于python机器学习人工智能方面的一些知识,但是验证码识别到现在都有没成功实现过,所以我就找了一个第三方打码平台(http://www.ttshitu.com/user/index.html)
资费很便宜,我充了一块钱到现在都没有花完,而且识别率也很高,很方便,适合小白入手
但还是很建议大家取试试自己写模型,嘿嘿嘿,学会了可以教教我哦!
还有一个困扰了我好久的问题,就是验证码图片的获取
大家可以看,验证码图片在网页中是有展示了,那应该很好获取呀,直接获取验证码图片url然后下载识别不就行了,嘿嘿,其实不然,你点开他的源码,发现
它的url并不能直接访问验证码图片地址,而且.aspx图片格式是随机生成的,你捕捉的验证码图片跟原来的验证码图片肯定不一致(访问一次刷新一次嘛),所以,我就使用了另一种方法,大家请看:
driver.save_screenshot("yzm.png")
ran = Image.open("yzm.png")
box = (1120, 630, 1180, 670) # 获取验证码位置,自动定位不是很明白,就使用了手动定位,代表(左,上,右,下)
ran.crop(box).save("yzm1.png")
img_path = "yzm1.png"
img = Image.open(img_path)
就是用save_screenshot函数将整个屏幕截图下来,再手动定位到验证码位置,生成一张新的验证码图片,当然,这种方法非常的片面,因为每个课程验证码的位置都是不同的,所以要具体课程具体定位咯
好了,本次的分享就到此结束啦,希望大家多多支持小编呀
大家还可以关注一下我自己的公众号,里面定期会推送一些python的小项目,大家可以一起学习交流呀!