技术| Python的从零开始系列连载(三十二)
综述
最近山大软件园校区QLSC_STU无线网掉线掉的厉害,连上之后平均十分钟左右掉线一次,很是让人心烦,还能不能愉快地上自习了?能忍吗?反正我是不能忍了,嗯,自己动手,丰衣足食!写个程序解决掉它!
假若你不能连这个无线,那就照照思路啦~
决战前夕
首先我们看一下那个验证页面是咋样滴,上个图先
嘿,这界面还算可以把,需要我们输入的东西就是俩,一个就是学号,另一个是身份证号后六位,然后就可以登录,享受免费的无线网啦。
不过不知道谁设置了个登录时长,一段时间后就会掉线了,于是,自动模拟登陆系统就要应运而生啦。
来,我们先点击一下连接,看一下浏览器怎么工作的。
按下F12,监听网络,我们点击第一个响应,也就是login.jsp,看一下。
我们具体看一下headers,里面form提交了什么东西,真的是茫茫多的数据啊。
嗯,一目了然POST的数据和提交的地址。 让我们来分析几个数据吧:
ClientIP:当前客户端的IP地址,在山大软件园校区这个地址是211.87开头的
timeoutvalue:连接等待时间,也就是俗话说的timeout
StartTime:登录时间,也就是在你登录的那一刻的时间戳,这个时间戳是13位的,精确到了毫秒,不过一般是10位的,我们加3个0就好了
shkOvertime:登录持续时间,这个数据默认是720,也就是12分钟之后,登录就失效了,自动掉线,我们可以手动更改
username:学号
password:密码,也就是我们身份证号后六位
我们需要在登录的时候把form表单中的所有信息都POST一下,然后就可以完成登录啦。 万事俱备,只欠东风,来来来,程序写起来!
一触即发
说走咱就走啊,天上的星星参北斗啊!
登陆地址:Request URL:http://192.168.8.10/portal/login.jsp?Flag=0
首先,我们需要验证一下IP地址,先写一个获取IP地址的函数,首先判断当前IP是不是211.87开头的,如果是的话,证明连接的IP是有效的。 首先我们写一个获取本机IP的方法:
self.ip_pre = "211.87" #获取本机无线IP def getIP(self): local_iP = socket.gethostbyname(socket.gethostname()) if self.ip_pre in str(local_iP): return str(local_iP) ip_lists = socket.gethostbyname_ex(socket.gethostname()) for ip_list in ip_lists: if isinstance(ip_list, list): for i in ip_list: if self.ip_pre in str(i): return str(i) elif type(ip_list) is types.StringType: if self.ip_pre in ip_list: return ip_list
这个方法利用了gethostbyname和gethostbyname_ex方法,获取了各个网卡的IP地址,遍历一下,找到那个211.87开头的IP,返回 接下来,获取到IP之后,我们便可以构建form,然后进行模拟登陆了。
#模拟登录 def login(self): print self.getCurrentTime(), u"正在尝试认证QLSC_STU无线网络" ip = self.getIP() data = { "username": self.username, "password": self.password, "serverType": "", "isSavePass": "on", "Submit1": "", "Language": "Chinese", "ClientIP": self.getIP(), "timeoutvalue": 45, "heartbeat": 240, "fastwebornot": False, "StartTime": self.getNowTime(), #持续时间,超过这个时间自动掉线,可进行设置 "shkOvertime": self.overtime, "strOSName": "", "iAdptIndex": "", "strAdptName": "", "strAdptStdName": "", "strFileEncoding": "", "PhysAddr": "", "bDHCPEnabled": "", "strIPAddrArray": "", "strMaskArray": "", "strMask": "", "iDHCPDelayTime": "", "iDHCPTryTimes": "", "strOldPrivateIP": self.getIP(), "strOldPublicIP": self.getIP(), "strPrivateIP": self.getIP(), "PublicIP": self.getIP(), "iIPCONFIG":0, "sHttpPrefix": "http://192.168.8.10", "title": "CAMS Portal" } #消息头 headers = { 'User-Agent' : 'Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.111 Safari/537.36', 'Host': '192.168.8.10', 'Origin': 'http://192.168.8.10', 'Referer': 'http://192.168.8.10/portal/index_default.jsp?Language=Chinese' } post_data = urllib.urlencode(data) login_url = "http://192.168.8.10/portal/login.jsp?Flag=0" request = urllib2.Request(login_url, post_data, headers) response = urllib2.urlopen(request) result = response.read().decode('gbk')
比较多的内容就在于form表单的数据内容以及请求头,后来利用urllib2的urlopen方法实现模拟登陆。
如果大家对此不熟悉,可以参见
Urllib的基本使用:http://cuiqingcai.com/947.html
这样,登录后的结果就会保存在result变量中,我们只需要从result中提取出我们需要的数据就可以了。
乘胜追击
接下来,我们就分析一下数据啦,结果有这么几种:
1.登录成功 2.已经登录 3.用户不存在 4.密码错误 5.未知错误
好,利用result分析一下结果
#打印登录结果 def getLoginResult(self, result): if u"用户上线成功" in result: print self.getCurrentTime(),u"用户上线成功,在线时长为",self.overtime/60,"分钟" elif u"您已经建立了连接" in result: print self.getCurrentTime(),u"您已经建立了连接,无需重复登陆" elif u"用户不存在" in result: print self.getCurrentTime(),u"用户不存在,请检查学号是否正确" elif u"用户密码错误" in result: pattern = re.compile('<td class="tWhite">.*?2553:(.*?)</b>.*?</td>', re.S) res = re.search(pattern, result) if res: print self.getCurrentTime(),res.group(1),u"请重新修改密码" else: print self.getCurrentTime(),u"未知错误,请检查学号密码是否正确"
通过字符串匹配和正则表达式,我们分辨并提取出了上述五种情况。
增加循环检测 既然是检测网络是否断开,那么我们只需要每隔一段时间检测一下就好了,那就10秒吧。
因为这个10秒是可配置的,为了方便配置,统一配置到__init__方法里面。
#检测间隔时间,单位为秒 self.every = 10
然后,我们写一个循环来检测一下
while True: nowIP = self.getIP() if not nowIP: print self.getCurrentTime(), u"请检查是否正常连接QLSC_STU无线网络" else: print self.getCurrentTime(),u"成功连接了QLSC_STU网络,本机IP为",nowIP self.login() while True: can_connect = self.canConnect() if not can_connect: nowIP = self.getIP() if not nowIP: print self.getCurrentTime(), u"当前已经断线,请确保连接上了QLSC_STU网络" else: print self.getCurrentTime(), u"当前已经断线,正在尝试重新连接" self.login() else: print self.getCurrentTime(), u"当前网络连接正常" time.sleep(self.every) time.sleep(self.every)
其中我们用到了canConnect方法,这个就是检测网络是否已经断开的方法,我们可以利用ping百度的方法来检测一下。
方法实现如下
#判断当前是否可以联网 def canConnect(self): fnull = open(os.devnull, 'w') result = subprocess.call('ping www.baidu.com', shell = True, stdout = fnull, stderr = fnull) fnull.close() if result: return False else: return True
好啦,所有的要点我们已经逐一击破,等着凯旋吧
收拾战场
好了,所有的代码要点已经被我们攻破了,接下来就整理一下,让他们组合起来,变成一个应用程序吧。
__author__ = 'CQC' #-*- coding:utf-8 -*- import urllib import urllib2 import socket import types import time import re import os import subprocess class Login: #初始化 def __init__(self): #学号密码 self.username = '201200131012' self.password = 'XXXXXX' #山大无线STU的IP网段 self.ip_pre = '211.87' #登录时长 self.overtime = 720 #检测间隔时间,单位为秒 self.every = 10 #模拟登录 def login(self): print self.getCurrentTime(), u"正在尝试认证QLSC_STU无线网络" ip = self.getIP() data = { "username": self.username, "password": self.password, "serverType": "", "isSavePass": "on", "Submit1": "", "Language": "Chinese", "ClientIP": self.getIP(), "timeoutvalue": 45, "heartbeat": 240, "fastwebornot": False, "StartTime": self.getNowTime(), #持续时间,超过这个时间自动掉线,可进行设置 "shkOvertime": self.overtime, "strOSName": "", "iAdptIndex": "", "strAdptName": "", "strAdptStdName": "", "strFileEncoding": "", "PhysAddr": "", "bDHCPEnabled": "", "strIPAddrArray": "", "strMaskArray": "", "strMask": "", "iDHCPDelayTime": "", "iDHCPTryTimes": "", "strOldPrivateIP": self.getIP(), "strOldPublicIP": self.getIP(), "strPrivateIP": self.getIP(), "PublicIP": self.getIP(), "iIPCONFIG":0, "sHttpPrefix": "http://192.168.8.10", "title": "CAMS Portal" } #消息头 headers = { 'User-Agent' : 'Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.111 Safari/537.36', 'Host': '192.168.8.10', 'Origin': 'http://192.168.8.10', 'Referer': 'http://192.168.8.10/portal/index_default.jsp?Language=Chinese' } post_data = urllib.urlencode(data) login_url = "http://192.168.8.10/portal/login.jsp?Flag=0" request = urllib2.Request(login_url, post_data, headers) response = urllib2.urlopen(request) result = response.read().decode('gbk') self.getLoginResult(result) #打印登录结果 def getLoginResult(self, result): if u"用户上线成功" in result: print self.getCurrentTime(),u"用户上线成功,在线时长为",self.overtime/60,"分钟" elif u"您已经建立了连接" in result: print self.getCurrentTime(),u"您已经建立了连接,无需重复登陆" elif u"用户不存在" in result: print self.getCurrentTime(),u"用户不存在,请检查学号是否正确" elif u"用户密码错误" in result: pattern = re.compile('<td class="tWhite">.*?2553:(.*?)</b>.*?</td>', re.S) res = re.search(pattern, result) if res: print self.getCurrentTime(),res.group(1),u"请重新修改密码" else: print self.getCurrentTime(),u"未知错误,请检查学号密码是否正确" #获取当前时间戳,13位 def getNowTime(self): return str(int(time.time()))+"000" #获取本机无线IP def getIP(self): local_iP = socket.gethostbyname(socket.gethostname()) if self.ip_pre in str(local_iP): return str(local_iP) ip_lists = socket.gethostbyname_ex(socket.gethostname()) for ip_list in ip_lists: if isinstance(ip_list, list): for i in ip_list: if self.ip_pre in str(i): return str(i) elif type(ip_list) is types.StringType: if self.ip_pre in ip_list: return ip_list #判断当前是否可以联网 def canConnect(self): fnull = open(os.devnull, 'w') result = subprocess.call('ping www.baidu.com', shell = True, stdout = fnull, stderr = fnull) fnull.close() if result: return False else: return True #获取当前时间 def getCurrentTime(self): return time.strftime('[%Y-%m-%d %H:%M:%S]',time.localtime(time.time())) #主函数 def main(self): print self.getCurrentTime(), u"您好,欢迎使用模拟登陆系统" while True: nowIP = self.getIP() if not nowIP: print self.getCurrentTime(), u"请检查是否正常连接QLSC_STU无线网络" else: print self.getCurrentTime(),u"成功连接了QLSC_STU网络,本机IP为",nowIP self.login() while True: can_connect = self.canConnect() if not can_connect: nowIP = self.getIP() if not nowIP: print self.getCurrentTime(), u"当前已经掉线,请确保连接上了QLSC_STU网络" else: print self.getCurrentTime(), u"当前已经掉线,正在尝试重新连接" self.login() else: print self.getCurrentTime(), u"当前网络连接正常" time.sleep(self.every) time.sleep(self.every) login = Login() login.main()
来,我们来运行一下,看下效果吧! 执行
python login.py
当前是可以联网的,我分别在网页上操作执行了断开,操作,程序自动检测到掉线,自动重新连接。
接下来我直接断开了QLSC_STU网络的链接,程序同样检测到QLSC_STU这个热点没有连接上,提示用户链接。
接下来我重新连接上了这个热点,由于刚才已经登录上线,且持续时间较短,网络自动恢复正常。
下面是运行结果:
嗯,这样我们就是实现了自动掉线的检测和模拟登录。
凯旋而归
咿呀伊尔哟,想约妹子上自习吗?那就赶紧来试试吧!一网在手,天下我有!追男神女神都不再是梦想!
如果有问题,欢迎留言讨论,代码肯定有不完善的地方,仅供参考。
原文发布时间为:2018-12-7
本文作者:灯塔大数据
本文来自云栖社区合作伙伴“灯塔大数据”,了解相关信息可以关注“DTbigdata”微信公众号
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
Golang 中的并发限制与超时控制
前言上回在 用 Go 写一个轻量级的 ssh 批量操作工具 里提及过,我们做 Golang 并发的时候要对并发进行限制,对 goroutine 的执行要有超时控制。那会没有细说,这里展开讨论一下。 以下示例代码全部可以直接在 The Go Playground 上运行测试: 并发我们先来跑一个简单的并发看看 1package main 2 3import ( 4 "fmt" 5 "time" 6) 7 8func run(task_id, sleeptime int, ch chan string) { 9 10 time.Sleep(time.Duration(sleeptime) * time.Second) 11 ch <- fmt.Sprintf("task id %d , sle
- 下一篇
Spring Flux中Request与HandlerMapping关系的形成过程
一、前言 Spring Flux中的核心DispatcherHandler的处理过程分为三步,其中首步就是通过HandlerMapping接口查找Request所对应的Handler。本文就是通过阅读源码的方式,分析一下HandlerMapping接口的实现者之一——RequestMappingHandlerMapping类,用于处理基于注解的路由策略,把所有用@Controller和@RequestMapping标记的类中的Handler识别出来,以便DispatcherHandler调用的。 HandlerMapping接口的另外两种实现类:1、RouterFunctionMapping用于函数式端点的路由;2、SimpleUrlHandlerMapping用于显式注册的URL模式与WebHandler配对。 文章系列 关于非阻塞IO:《从时间碎片角度理解阻塞IO模型及非阻塞模型》 关于SpringFlux新手入门:《快速上手Spring Flux框架》 Spring Flux中Request与HandlerMapping关系的形成过程 本文 二、对基于注解的路由控制器的抽象 Sp...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Linux系统CentOS6、CentOS7手动修改IP地址
- CentOS6,7,8上安装Nginx,支持https2.0的开启
- Windows10,CentOS7,CentOS8安装MongoDB4.0.16
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- CentOS7安装Docker,走上虚拟化容器引擎之路
- CentOS6,CentOS7官方镜像安装Oracle11G
- CentOS8编译安装MySQL8.0.19