闲来无事,由于校园内网络是限流量的,查询流量很是频繁,于是萌生了写一个本地脚本进行一键查询自己的剩余流量。

整个部分可以分为三个过程进行:

  1. 对登陆时http协议进行分析
  2. 利用python进行相关的模拟登陆
  3. 后期整合

第一部分:对登陆时http协议进行分析

  模拟浏览器进行登陆,那么就需要知道当浏览器进行登陆时发生了什么事情。对此可以参见下面这张自制的图,它展示了一次浏览器访问一个地址的全过程。

  pytho简单爬虫_模拟登陆西电流量查询_实现一键查询自己的校园网流量

图1 浏览器在地址框输入一个地址后发生的事情

  参考自:http://www.linux178.com/web/httprequest.html

  对于本部分来说,我们只需要关系途中的3和4过程,即http协议请求及服务器响应http协议请求返回html文件。

  由图可知,http协议请求分为三部分:起始行,头部,主体。既然我们是模拟浏览器登陆进行,那么浏览器的这些信息是怎么填的呢?这个可以通过浏览器自带的开发者工具看到,我所使用的浏览器是chorm,通过点击右上角的按钮,然后“更多工具——开发者工具”,之后选择其中的Network选项,效果如下图所示

pytho简单爬虫_模拟登陆西电流量查询_实现一键查询自己的校园网流量

图2 浏览器的开发者工具

  将上面的内容清空后,输入能够登录查询的网址。具体例子是我们学校为http://zyzfw.xidian.edu.cn/ 详情见图3

  pytho简单爬虫_模拟登陆西电流量查询_实现一键查询自己的校园网流量

图3 查询http协议信息

  之后就可以看见协议中相关部分所填内容。但这并非我们所要的东西,我们所需要的是模拟登陆的过程,也就是说需要的是在我们填好账号密码验证码后点击登陆所发生的动作。因此应该去找点击登陆后所发出的请求内容是什么(在这里可以通过输入错误的密码来查看所发出的内容是什么,以免页面跳转后突然弹出大量的通信将我们所需要的信息淹没),头部信息如图4

pytho简单爬虫_模拟登陆西电流量查询_实现一键查询自己的校园网流量

图4 头部信息

  其中具体每一项什么作用可以参考这两个文章,讲的很细致很有条理

  https://www.zybuluo.com/yangfch3/note/167490

  http://www.cnblogs.com/li0803/archive/2008/11/03/1324746.html

  我们模拟登陆所需要的为图4中的Host Referer User-Agent 以及图5中的数据主体

pytho简单爬虫_模拟登陆西电流量查询_实现一键查询自己的校园网流量

图5 数据主体

  当我们把这些信息都搞到手后,就可以开始模拟浏览器登陆过程了。

  整理一下,在本网站登陆所用的请求方法为“POST” 其采用的简单安全措施为__crsf 与验证码 因此下一步的主要工作就是讲验证码与__crsf问题搞定

 第二部分:利用python进行模拟登陆

  此部分参考:https://github.com/xchaoinfo/fuck-login/blob/master/001%20zhihu/zhihu.py

   首先,构造头部信息(最好在字符串前加上r,防止某些转义问题)

url_login=r'http://zyzfw.xidian.edu.cn/'
postdata={'LoginForm[username]':'1503*****','LoginForm[password]':'*****'}
agent=r'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36'
headers = {
    "Host": "zyzfw.xidian.edu.cn",
    "Referer": r"http://zyzfw.xidian.edu.cn/",
    'User-Agent': agent
}

  由于有验证码的存在,因此需要将验证码得到,具体如下:

def get_captcha():
    t = str(int(time.time() * 1000))
    captcha_url = 'http://zyzfw.xidian.edu.cn/site/captcha?refresh=1&_=' + t 
    r = session.get(captcha_url, headers=headers)
#两层get
    tem=r.json()['url']
    captcha_url='http://zyzfw.xidian.edu.cn'+tem
    r=session.get(captcha_url,headers=headers)
    with open('captcha.jpg', 'wb') as f:
        f.write(r.content)
        f.close()
    # 用pillow 的 Image 显示验证码
    # 如果没有安装 pillow 到源代码所在的目录去找到验证码然后手动输入
    try:
        im = Image.open('captcha.jpg')
        im.show()
        im.close()
    except:
        print(u'请到 %s 目录找到captcha.jpg 手动输入' % os.path.abspath('captcha.jpg'))
    captcha = input("please input the captcha\n>")
    return captcha

  其中的那个验证码的地址,通过和第一部分同样的方法,找到其获取验证码的地址(我测试的几个网站验证码获取地址都和时间有关),将验证码图片下载保存下来后就可以进行验证码的读取工作。

  只有在进行__xsrf参数的获取,过程类似,如下:

def get_csrf():
    '''_csrf 是一个动态变化的参数'''
    index_url = 'http://zyzfw.xidian.edu.cn'
    # 获取登录时需要用到的_xsrf
    index_page = session.get(index_url, headers=headers)
    html = index_page.text
    pattern = r'name="_csrf" value="(.*?)"'
    # 这里的_xsrf 返回的是一个list
    _xsrf = re.findall(pattern, html)
    return _xsrf[0]

  其中涉及到简单的字符串匹配,使用简单的正则匹配就可以提取出相应的数据。

  至此,我们完成了该数据准备工作,,下一步就是开始模拟登陆,如下:

postdata['_csrf']=get_csrf()
postdata['LoginForm[verifyCode]']=get_captcha()
result=session.post(url_login,data=postdata,headers=headers)

第三部分:后期处理

  html拿到手之后,剩下的就是进行对html解析,将自己需要的信息通过正则匹配拿出来就行。

  之后在写一个批处理,做到一键查询的功能,效果如下:

  pytho简单爬虫_模拟登陆西电流量查询_实现一键查询自己的校园网流量

 

至此,最终完成了一个简易版的一键流量查询。

 

展望:此程序由于没有进行自动的验证码识别,所以输入验证码是一大瑕疵,如果能够做到自动识别验证码,那么将是真正的一键查询,下一步主要就此问题进行解决。