python+selenium实现自动化连接校园网(资源下载链接在总结

校园网的自动连接

在学校里面,我经常会用到校园WiFi。我个人使用的是办移动套餐送的wifi套餐,因此,我连接的WiFi是NJUPT-CMCC。当我写出来这个代码的时候,我发给我舍友,他们都说直接用chrome就可以实现记住账号密码,点一下就可以实现了登录,为什么还要特意使用一个程序占内存呢?
不知道是不是只有我一个人遇到过这种情况,我在连接NJUPT-CMCC的时候,会随机出现三个页面——上网登录窗、信息页、认证成功页,有的时候我是可以一次登陆成功,但是更多的是出现信息页,在这个页面我还得返回一次,再去登陆一次,我就很烦!所以,我就写了这个代码,仅供参考。本文的内容全部是基于该背景来分享。

多个页面的识别与判断

页面分为三个——上网登录窗、信息页、认证成功页。
这三个页面的识别一开始我使用的是selenium的CSS选择器去进行识别的,后来在别的贴子发现可以直接使用title,但我的代码里面还是沿用CSS选择器,因为作用都一样。

page_information = driver.find_element_by_css_selector('head > title').get_attribute('textContent')

获取了页面title之后,开始对title进行全字符匹配判别

#back()表示遇到信息页的方法 
#quit()表示遇到认证成功页的方法

if page_information == '上网登录窗':
		pass
	elif page_information == '信息页':
		back()
	elif page_information == '认证成功页':
		quit()
	#最后无论是哪个页面,还是得进行登录操作。
	login(account, password)

login()

先上代码

def login(account, password):
	print(account, password)
	input_account = wait.until(EC.presence_of_all_elements_located((By.CSS_SELECTOR, '#edit_body > div.edit_row.ui-resizable-autohide > div.edit_loginBox.ui-resizable-autohide > form > input:nth-child(3)')))
	input_password = wait.until(EC.presence_of_all_elements_located((By.CSS_SELECTOR, '#edit_body > div.edit_row.ui-resizable-autohide > div.edit_loginBox.ui-resizable-autohide > form > input:nth-child(4)')))
	button = driver.find_element_by_css_selector('#edit_body > div.edit_row.ui-resizable-autohide > div.edit_loginBox.ui-resizable-autohide > form > input:nth-child(2)')

	input_account[0].send_keys(account)
	input_password[0].send_keys(password)
	print("准备点击")
	button.click()

(里面的一些print是为了让我方便进行调试而用的,对代码运行没有影响。)
selenium去获取上网登录窗页面上的两个文本框,还有登录按钮都是用的CSSselector,然后对这两个文本框进行输入account&password。

back()

def back():
	button_back = driver.find_element_by_css_selector('#edit_body > div > div.edit_loginBox.ui-resizable-autohide > form > input')
	button_back.click()

在遇到信息页的时候的处理方法很简单,获取了返回按钮之后就返回上网登录窗页面。

quit()

def quit():
	button_quit = driver.find_element_by_css_selector('#edit_body > div > div.edit_loginBox.ui-resizable-autohide > form > input')
	button_quit.click()
	time.sleep(2)
	confirm = driver.switch_to.alert
	confirm.accept()
	print('你刚刚确认下线')
	time.sleep(5)
	confirm.accept()
	print('现在返回上网登录窗页面')

如果代码刚开始运行的时候检测到是在认证成功页(但是没网),那就会调用到quit的方法,通过这个去注销账号密码,回到上网登录窗页面,再进行login。
这个窗口返回的过程中涉及到弹出两个提示框,这两个是这段代码新的内容,涉及到alert的语句就是用来处理这个的。至于等待时间,我在这里使用的是固定时间,与前面使用的自动判断时间不一样。

是否成功登陆了呢?

def Is_OK():
	#判断跳转界面
	driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
	page_information = driver.find_element_by_css_selector('head > title').get_attribute('textContent')

	if page_information == '认证成功页':
		print("login successfully")
	else:
		print("出现信息页,正在返回准备重新登录")
		back()
		login(account, password)

这段代码是在登陆完成之后去检查是否完成了登录,检查原理还是一样,去识别不同页面的title,在代码中我调用了两次这个方法,进行二次认证。
但是,在这里会出现一个问题,就是两次认证都失败的话程序还是会照常结束,遇到这种情况的话就是用户自己输入的账号密码出错了,但我在这里没有设置这点,所以如果大家使用出现这种情况的话,一定要检查自己的账号密码是不是错了:检查的方法可以是自己去查看同路径下的txt文件,然后可以选择修改文件内容也可以直接删除文件在下一次运行程序的时候重新输入账号密码。

本地保存账号密码

在这里,我选择的是将账号密码保存在本地的同路径的一个txt文件内。然后,每一次都会自动去检查该文件是否存在,不存在的话会提示用户重新输入账号密码并保存一份新的文件,所以大家千万不要删除该txt文件或者更改名字,另外就是,这份文件只能储存一个人的账号密码信息,因为想到毕竟是个人电脑使用的情况较多,而且这么做页简单很多。

def txt_handle():
	global account, password
	try:
		f = open('校园网登录信息文件.txt', "r", encoding="utf-8")
		lines = f.readlines()
		print("已进入")
		account = lines[0]
		account = account.replace('\n', '')
		password = lines[1]
		f.close()
		print(account, password)

	except Exception as e:
		account = input("请输入账号:")
		password = input("请输入密码:")
		txt = account + '\n' + password
		print(account, password)

		f = open('校园网登录信息文件.txt', "w+", encoding="utf-8")
		f.write(txt)
		print("文件信息已写入,请勿删除该文件!")
		f.close()
	return account, password

全部代码

#login_selenium.py
from selenium import webdriver
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
from selenium.common.exceptions import TimeoutException
from selenium.webdriver.common.by import By
import time, os
''' NJUPT-CMCC/ChinaNet自动登录代码 author:海hong 本功能主要实现了对于登陆页面三个窗口的识别以及账号密码保存在本地的功能。 通过第一次登陆需要输入账号密码,以后登录就是一键便可完成,时间也很快,目前测试暂时没见bug。 '''
def txt_handle():
global account, password
try:
f = open('校园网登录信息文件.txt', "r", encoding="utf-8")
lines = f.readlines()
print("已进入")
account = lines[0]
account = account.replace('\n', '')
password = lines[1]
f.close()
print(account, password)
except Exception as e:
account = input("请输入账号:")
password = input("请输入密码:")
txt = account + '\n' + password
print(account, password)
f = open('校园网登录信息文件.txt', "w+", encoding="utf-8")
f.write(txt)
print("文件信息已写入,请勿删除该文件!")
f.close()
return account, password
def login(account, password):
print(account, password)
input_account = wait.until(EC.presence_of_all_elements_located((By.CSS_SELECTOR, '#edit_body > div.edit_row.ui-resizable-autohide > div.edit_loginBox.ui-resizable-autohide > form > input:nth-child(3)')))
input_password = wait.until(EC.presence_of_all_elements_located((By.CSS_SELECTOR, '#edit_body > div.edit_row.ui-resizable-autohide > div.edit_loginBox.ui-resizable-autohide > form > input:nth-child(4)')))
button = driver.find_element_by_css_selector('#edit_body > div.edit_row.ui-resizable-autohide > div.edit_loginBox.ui-resizable-autohide > form > input:nth-child(2)')
input_account[0].send_keys(account)
input_password[0].send_keys(password)
print("准备点击")
button.click()
def back():
button_back = driver.find_element_by_css_selector('#edit_body > div > div.edit_loginBox.ui-resizable-autohide > form > input')
button_back.click()
def quit():
button_quit = driver.find_element_by_css_selector('#edit_body > div > div.edit_loginBox.ui-resizable-autohide > form > input')
button_quit.click()
time.sleep(2)
confirm = driver.switch_to.alert
confirm.accept()
print('你刚刚确认下线')
time.sleep(5)
confirm.accept()
print('现在返回上网登录窗页面')
def Is_OK():
#判断跳转界面
driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
page_information = driver.find_element_by_css_selector('head > title').get_attribute('textContent')
if page_information == '认证成功页':
print("login successfully")
else:
print("出现信息页,正在返回准备重新登录")
back()
login(account, password)
def Is_page():
#判断跳转界面
driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
page_information = driver.find_element_by_css_selector('head > title').get_attribute('textContent')
if page_information == '上网登录窗':
pass
elif page_information == '信息页':
back()
elif page_information == '认证成功页':
quit()
login(account, password)
#检测页面是否跳转到认证成功页
Is_OK()
print("通过第一次验证")
Is_OK()
print("通过第二次验证,成功登录")
url = 'http://p.njupt.edu.cn'
driver = webdriver.Chrome()
wait = WebDriverWait(driver, 10)
driver.get(url)
account = 'XXXXXXXXXX'
password = 'XXXXXX'
txt_handle()
print(account, password)
Is_page()
driver.close()
#print("5秒后窗口自动关闭")
#time.sleep(5)
#os.sys.exit()

注意事项——chromedriver

driver = webdriver.Chrome()
wait = WebDriverWait(driver, 10)
driver.get(url)

第一行代码,我是之前就已经在chrome的安装目录下放置了chromedriver.exe,因此我这里可以直接引用;如果你是第一次接触到chrome driver,那么你得去下载一个匹配自己chrome版本的driver(一定要是版本匹配),推荐到国内镜像网站下载。关于看自己chrome的版本可以在地址栏输入chrome://version/来查看(图中红框位置)

如果,你下载下来的chromedriver没有放置在chrome的安装路径下,放在与该代码同一个文件夹下,那么,你需要将第一条语句改成成:

driver = webdriver.Chrome('chromedriver.exe')

这样下来,代码运行应该是没有很大的问题了。

问题修改

Q1:运行完代码后,CMD窗口不能自动退出。

driver.close()
#更改上条语句为下面:
driver.quit()

Q2:关于自动登陆的验证
具体内容请看我下一篇文章

Q3:关于开机自启问题
具体内容可以看CSDN上另一个博主的文章python+windows任务计划程序实现每日定时登录校园网。我在它的基础上进行了任务计划程序的修改,我修改成了每次登陆时,于是我电脑桌面现在也不用保留这个txt以及py的文件,除了开机之后桌面会出现大黑框10秒左右之外,真正给我带来了类似我自己在家上网的舒服度——开机即有网。

总结

代码不难,但是需要生成exe文件去服务大众还是有一定的距离,对方的电脑上如果没有python、chrome driver环境的话好像是运行不了。但这个对于电脑上有python的人来说就有帮助,起码减少了许多的麻烦。
文章中我提到的那个小bug,我在Java上面已经修复了,只是不想再改动一次python的代码了,关于Java的代码,预计也是在这两三天我会再写一篇文章发上来,上面使用到的方法跟这个有不一样的地方,还是挺有趣的。希望大家到时留心关注我的下一篇博客。
关于python的这部分代码,我从最初的50行解决自身笔记本上网问题,到后来一点点问题去修改,写到了现在的近150行,可以说,一般情况下会出现的问题我里面都会有相应的处理机制,但是限于水平有限,有的部分问题还是只能靠人工去判断(比如深夜断网、账号密码出错)。
关于兼容性问题,我这次做了妥协,本来想的是自动判断电脑上使用的是哪一款浏览器,我就自动匹配相应的driver,但是发现这样下来的话,大家需要下载的文件太大,还不如就统一标准,大家都用chrome,这样是种更加省事的方式。
这次代码我是打包成了exe文件,大家的电脑上没有安装python、selenium的都是可以正常使用的,具体下载链接我将会放在我的百度网盘上,以供大家使用。
百度网盘链接
如果有疑问,欢迎大家在下面留言,我看到的话都会尽快回复的。

参考过的博客

1
2
3
4
5
自己曾经用requests写的自动登录脚本(涉及到一些没有说到的基础问题)

本文地址:https://blog.csdn.net/haihonga/article/details/110427359