码迷,mamicode.com
首页 > 编程语言 > 详细

Python实现自动登录/登出校园网网关

时间:2015-10-23 01:32:57      阅读:709      评论:0      收藏:0      [点我收藏+]

标签:

    学校校园网的网络连接有免费连接和收费连接两种类型,可想而知收费连接浏览体验更佳,比如可以访问更多的网站。之前收费地址只能开通包月服务才可使用,后来居然有了每个月60小时的免费使用收费地址的优惠。但是,一旦连接了收费地址而忘记及时断开,60小时会很快用完。 
    为了节约收费地址的使用时间,采用如下方案:每隔1个小时,都在本机上断开校园网的收费连接,同时连接免费连接,这样,每次手动连接收费连接之后,最多使用1个小时,就会被自动断开。

1. python实现连接/断开网络连接 
     通过执行python脚本,实现访问 its.pku.edu.cn 并设置连接/断开。 
通过fiddler抓包,分析从访问 its.pku.edu.cn,到填写账号密码,再到最后登陆成功的过程中,浏览器和网关交互的http request和response。 
发现: 
(1)访问 http://its.pku.edu.cn 
技术分享

request如下图: 
技术分享
网关response如下: 
技术分享
注意其中的%7C%3BkiDrqvfi7d%24v0p5Fg72Vwbv2%3B%7C 字符串,该字符串在后续的post中被使用。

(2)填写账号密码,连接到地址http://its.pku.edu.cn/cas/login,request中的文本为: 
技术分享
发现其中含有账号和密码,以及&pwd_t=%E5%AF%86%E7%A0%81(这个是固定的字符),还有字符串%7C%3BkiDrqvfi7d%24v0p5Fg72Vwbv2%3B%7C(这是从上次的response中获得的)。 
... 
中间浏览器还连接了 
http://its.pku.edu.cn/netportal/ 
http://its.pku.edu.cn/netportal/netportal_UTF-8.jsp 
http://its.pku.edu.cn/netportal/blank_UTF-8.html 
http://its.pku.edu.cn/connect.htm
 
等url,通过单步跟踪发现,这些url对最终的网络连接成功与否没有任何影响,因此不予考虑。 
... 
(3)设置连接操作,浏览器连接到 http://its.pku.edu.cn/netportal/ipgwopen?sid=449 
    现在要知道449 是如何来的,从前面的浏览器和网关之间交互的几个response中没有发现449,考虑449可能是由函数生成的。在url http://its.pku.edu.cn/netportal/js/funcs_v2.js?509173 的response中发现了

    function doaction3(_d){
    if(_d.indexOf("?")!=-1){
    window.frames[‘mycontent‘].location.href=_d+"&sid="+Math.floor(Math.random()*1000);
    }else{
    window.frames[‘mycontent‘].location.href=_d+"?sid="+Math.floor(Math.random()*1000);
    }}

 

的js函数,原来449是随机生成的一个值。 
    注意到http://its.pku.edu.cn/netportal/ipgwopen?sid=449中的 ipgwopen,这个是连接的类型表示,通过分析http://its.pku.edu.cn/netportal/netportal_UTF-8.jsp的response内容可以发现: 
ipgwopen 表示连接免费地址 
ipgwopenall 表示连接免费和收费地址 
ipgwclose 表示断开本机连接 
ipgwcloseall 表示断开所有连接 

    步骤(3)之后,发现就可以正常上网,因此在使用python模拟浏览器登录网关的时候,只需要模拟1-3这三个步骤即可,需要注意获取步骤1 response中的字符串,并在步骤2中post到网关,以及步骤3的sid为随机生成的整数。

python代码实现 
源代码使用python3 实现,因此需要机器安装 python3 环境。

#!/usr/bin/env python3
‘‘‘python crawler ‘‘‘
#encoding:UTF-8

import re
import os
import gzip
import random
import sys
import time
import urllib
import urllib.request
import http.cookiejar
import http.client

def MakeOpener(head = { 
            ‘Connetion‘: ‘Keep-Alive‘,          
            ‘Accept‘: ‘text/html, application/xhtml+xml, */*‘,
            ‘Accept-Language‘: ‘en-US, en;q=0.8,zh-Hans-CN;q=0.5,zh-Hans;q=0.3‘,
            ‘User-Agent‘: ‘Mozilla/5.0 (Windows NT 6.3; Win64; x64; rv:39.0) Gecko/20100101 Firefox/39.0‘}):

    cj = http.cookiejar.CookieJar()
    pro = urllib.request.HTTPCookieProcessor(cj) #Python自动处理cookie
    opener = urllib.request.build_opener(pro)    #用于打开url的opener
#    urllib.request.install_opener(opener)
    SetOpenerHeader(opener, head)                #构造http头部数据,模仿一个浏览器对url进行访问
    return opener

#构造 opener的头部信息, 参数header为一个字典,如上面的 ‘Connetion‘: ‘Keep-Alive‘, ‘Accept‘: ‘text/html, application/xhtml+xml, */*‘,
#将字典中的key和value对,变成元组(k,v)然后加入到 opener的 addheaders 列表中
def SetOpenerHeader(opener, header):
    tmp_header = []
    for key, value in header.items():
        elem = (key, value)
        tmp_header.append(elem)
    opener.addheaders = tmp_header

#http返回的数据可能为经过压缩的,若网页经过压缩,则解压。此时得到的数据为字节数组,然后将网页按照字符编码解析这些字节数组
#将字节数组翻译为 字符串
def DecodePageData(data):
    try:
        data = gzip.decompress(data)
    except:
#        print(‘exception occurs when decompress as gzip‘)
        pass

    result = data

    encode_options = [‘utf-8‘, ‘GBK‘, ‘gb2312‘]
    for encode_op in encode_options:    #尝试多种编码的解析,将http 返回的数据(字节数组)翻译为字符串
        try:
            result = data.decode(encode_op)
        except:
            continue
        else:
            break

    return result

def GetEncodedPostData(page_data, username1, password, free_gw = True):
    #获取服务端进行验证的一个字符串,通过fiddler中对比知道,需要在本地下次post的时候,添加这个验证字符串
    cer = re.compile(r‘\(\"username\"\)\.value\+unescape\(\"(.+)\"\)\+‘)

    encode_str = ‘‘
    for m in cer.finditer(page_data):
        encode_str = m.group(1)
        break

    if not encode_str:
        print(‘parse username generating formula failed...‘)
        return

    result = ‘username1=‘ + username1
    result += ‘&password=‘
    result += password
    result += ‘&pwd_t=%E5%AF%86%E7%A0%81‘
    result += ‘&fwrd=‘
    if free_gw:
        result += ‘free‘
    else:
        result += ‘fee‘
        
    result += ‘&username=‘
    result += username1
    result += encode_str
    result += password
    result += encode_str
    if free_gw:
        result += ‘12‘
    else:
        result += ‘11‘

    return result

#根据option执行不同的操作, user_name 和 passwd 为校园网账户和密码
def PkuGateWayOperation(option, user_name = ‘1401214230‘, passwd = ‘xxxxx‘):
    #伪造的一个浏览器访问url的http头部
    header = { 
            ‘Connection‘: ‘Keep-Alive‘,
            ‘Accept‘: ‘*/*‘,
            ‘Accept-Language‘: ‘en-US, en;q=0.8,zh-Hans-CN;q=0.5,zh-Hans;q=0.3‘,
            ‘User-Agent‘: ‘Mozilla/5.0 (Windows NT 6.3; Win64; x64; rv:39.0) Gecko/20100101 Firefox/39.0‘,
            ‘Accept-Encoding‘: ‘gzip, deflate‘, 
            ‘Host‘: ‘its.pku.edu.cn‘ 
            }

    #第一步,模拟浏览器登录 http://its.pku.edu.cn/
    url = ‘http://its.pku.edu.cn/‘
    opener = MakeOpener(header)
    op = opener.open(url)

    data = DecodePageData(op.read())

    header[‘Referer‘] =  ‘http://its.pku.edu.cn/‘
    url = ‘http://its.pku.edu.cn/cas/login‘
    SetOpenerHeader(opener, header)

    free_gw = True
    if (option == 2):
        free_gw = False
    
    #根据返回的网页数据,设置post数据,主要是用户名、密码、连接方式
    post_data = GetEncodedPostData(data, user_name, passwd, free_gw)   
    
    #第二步,post用户名和密码,在 post_data中,其中还添加了一些验证信息(从上一次response中获取)
    op = opener.open(url, post_data.encode(encoding=‘utf-8‘))

    option_str = ‘ipgwopen‘
    if option == 2:
        option_str = ‘ipgwopenall‘
    elif option == 3:
        option_str = ‘ipgwclose‘
    elif option == 4:
        option_str = ‘ipgwcloseall‘

    #添加操作选项 和一个随机数! 
    url = ‘http://its.pku.edu.cn/netportal/‘ + option_str + ‘?sid=‘ + str(random.randint(1,999))
    #第三部,设置连接操作
    op = opener.open(url)


#命令行参数,来设置不同的操作
#1 连接免费网址
#2 连接收费网址
#3 断开本机连接
#4 断开所有连接
#5 断开本机连接,然后重新连接免费地址(这样是为了设置程序每隔1个小时执行一次,防止收费地址连接时间过长。定时断网,节约收费地址的使用时间)
if __name__ == ‘__main__‘:
    if len(sys.argv) != 2:
        print(‘usage <option: 1 (connect free), 2 (connect global), 3 (disconnect this computer), 4 (disconnect all), 5(disconnect this computer and connect free)‘)
        exit(1)

    option = int(sys.argv[1])
    if option < 1 or option > 5:
        print(‘invalid option number: ‘ + sys.argv[1])
        print(‘usage <option: 1 (connect free), 2 (connect global), 3 (disconnect this computer), 4 (disconnect all), 5(disconnect this computer and connect free)‘)
        exit(1)

    if option == 5:
        PkuGateWayOperation(3)
        PkuGateWayOperation(1)
        
        fb = open(‘G:\\workspace\\MyTools\\Python\\log.txt‘, ‘a‘)
        fb.write(‘this program runs at ‘ + time.strftime(‘%Y-%m-%d %H:%M:%S‘,time.localtime(time.time())) )
        fb.close()
    else:
        PkuGateWayOperation(option)

 

2. 每1小时自动执行 
    linux下比较方便,直接设置 crontab即可。 
    windows下可以设置机器的自动任务计划,具体步骤如下: 
(1)开始->所有工具->windows管理工具->任务计划程序 
(2)创建任务 
(2.1)常规 ——填写程序名称(随意) 
(2.2)触发器 ——新建,设置为每天固定时间开始执行,每隔一个小时重复一次 
技术分享

(2.3)操作 ——新建,设置为执行python脚本,且设置正确的命令行参数 (包括python脚本路径和参数5)
技术分享

Python实现自动登录/登出校园网网关

标签:

原文地址:http://www.cnblogs.com/gtarcoder/p/4903253.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!