技术| Python的从零开始系列连载(三十二)

简介:

综述
最近山大软件园校区QLSC_STU无线网掉线掉的厉害,连上之后平均十分钟左右掉线一次,很是让人心烦,还能不能愉快地上自习了?能忍吗?反正我是不能忍了,嗯,自己动手,丰衣足食!写个程序解决掉它!

假若你不能连这个无线,那就照照思路啦~

决战前夕
首先我们看一下那个验证页面是咋样滴,上个图先
13
嘿,这界面还算可以把,需要我们输入的东西就是俩,一个就是学号,另一个是身份证号后六位,然后就可以登录,享受免费的无线网啦。

不过不知道谁设置了个登录时长,一段时间后就会掉线了,于是,自动模拟登陆系统就要应运而生啦。

来,我们先点击一下连接,看一下浏览器怎么工作的。

按下F12,监听网络,我们点击第一个响应,也就是login.jsp,看一下。
14
我们具体看一下headers,里面form提交了什么东西,真的是茫茫多的数据啊。
15
嗯,一目了然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这个热点没有连接上,提示用户链接。

接下来我重新连接上了这个热点,由于刚才已经登录上线,且持续时间较短,网络自动恢复正常。

下面是运行结果:
16
嗯,这样我们就是实现了自动掉线的检测和模拟登录。

凯旋而归
咿呀伊尔哟,想约妹子上自习吗?那就赶紧来试试吧!一网在手,天下我有!追男神女神都不再是梦想!

如果有问题,欢迎留言讨论,代码肯定有不完善的地方,仅供参考。

原文发布时间为:2018-12-7
本文作者:灯塔大数据
本文来自云栖社区合作伙伴“灯塔大数据”,了解相关信息可以关注“DTbigdata”微信公众号

相关文章
|
9天前
|
算法 Python
Python图论探索:从理论到实践,DFS与BFS遍历技巧让你秒变技术大牛
图论在数据结构与算法中占据重要地位,应用广泛。本文通过Python代码实现深度优先搜索(DFS)和广度优先搜索(BFS),帮助读者掌握图的遍历技巧。DFS沿路径深入搜索,BFS逐层向外扩展,两者各具优势。掌握这些技巧,为解决复杂问题打下坚实基础。
21 2
|
11天前
|
开发框架 开发者 Python
探索Python中的装饰器:技术感悟与实践
【10月更文挑战第31天】 在编程世界中,装饰器是Python中一种强大的工具,它允许我们在不修改函数代码的情况下增强函数的功能。本文将通过浅显易懂的方式,带你了解装饰器的概念、实现原理及其在实际开发中的应用。我们将一起探索如何利用装饰器简化代码、提高可读性和复用性,同时也会分享一些个人的技术感悟,帮助你更好地掌握这项技术。
27 2
|
15天前
|
数据采集 Web App开发 iOS开发
如何利用 Python 的爬虫技术获取淘宝天猫商品的价格信息?
本文介绍了使用 Python 爬虫技术获取淘宝天猫商品价格信息的两种方法。方法一使用 Selenium 模拟浏览器操作,通过定位页面元素获取价格;方法二使用 Requests 和正则表达式直接请求页面内容并提取价格。每种方法都有详细步骤和代码示例,但需注意反爬措施和法律法规。
|
16天前
|
数据采集 存储 Web App开发
利用Python 的爬虫技术淘宝天猫销量和库存
使用 Python 爬虫技术获取淘宝天猫商品销量和库存的步骤包括:1. 安装 Python 和相关库(如 selenium、pandas),下载浏览器驱动;2. 使用 selenium 登录淘宝或天猫;3. 访问商品页面,分析网页结构,提取销量和库存信息;4. 处理和存储数据。注意网页结构可能变化,需遵守法律法规。
|
17天前
|
数据库 开发者 Python
“Python异步编程革命:如何从编程新手蜕变为并发大师,掌握未来技术的制胜法宝”
【10月更文挑战第25天】介绍了Python异步编程的基础和高级技巧。文章从同步与异步编程的区别入手,逐步讲解了如何使用`asyncio`库和`async`/`await`关键字进行异步编程。通过对比传统多线程,展示了异步编程在I/O密集型任务中的优势,并提供了最佳实践建议。
16 1
|
30天前
|
人工智能 文字识别 Java
SpringCloud+Python 混合微服务,如何打造AI分布式业务应用的技术底层?
尼恩,一位拥有20年架构经验的老架构师,通过其深厚的架构功力,成功指导了一位9年经验的网易工程师转型为大模型架构师,薪资逆涨50%,年薪近80W。尼恩的指导不仅帮助这位工程师在一年内成为大模型架构师,还让他管理起了10人团队,产品成功应用于多家大中型企业。尼恩因此决定编写《LLM大模型学习圣经》系列,帮助更多人掌握大模型架构,实现职业跃迁。该系列包括《从0到1吃透Transformer技术底座》、《从0到1精通RAG架构》等,旨在系统化、体系化地讲解大模型技术,助力读者实现“offer直提”。此外,尼恩还分享了多个技术圣经,如《NIO圣经》、《Docker圣经》等,帮助读者深入理解核心技术。
SpringCloud+Python 混合微服务,如何打造AI分布式业务应用的技术底层?
|
1月前
|
存储 数据可视化 Python
Python编程中的数据可视化技术
在数据驱动的世界中,将复杂的数据集转换为易于理解的视觉表示形式至关重要。本文将深入探讨如何使用Python进行数据可视化,包括选择合适的库、处理数据和设计有效的图表。我们将一起学习如何让数据讲故事,并确保你的信息传达清晰且有影响力。
|
1月前
|
网络协议 安全 Java
难懂,误点!将多线程技术应用于Python的异步事件循环
难懂,误点!将多线程技术应用于Python的异步事件循环
61 0
|
1月前
|
数据挖掘 计算机视觉 Python
基于Python的简单图像处理技术
【10月更文挑战第4天】在数字时代,图像处理已成为不可或缺的技能。本文通过Python语言,介绍了图像处理的基本方法,包括图像读取、显示、编辑和保存。我们将一起探索如何使用PIL库进行图像操作,并通过实际代码示例加深理解。无论你是编程新手还是图像处理爱好者,这篇文章都将为你打开一扇新窗,让你看到编程与创意结合的无限可能。
|
1月前
|
安全 测试技术 Go
Python 和 Go 实现 AES 加密算法的技术详解
Python 和 Go 实现 AES 加密算法的技术详解
75 0