python抢课程序_一个Python抢课脚本

webchat.jpg

如果没有过抢课的经历可以说是白读四年大学了,每次抢课玩的就是速度与激情,最近在学Python爬虫相关,正好可以当一次实战练习,这次使用Python标准库中的urllib与urllib2,其带有http的服务器端和客户端的应用支持。

折腾前准备Python2.7

Chrome中的开发者工具

有人说Python 2和Python 3是两门完全不同的语言,关于Python版本之争就不多说了,反正萝卜白菜各有所爱,由于关于Python3的教程太少所以我就选2.7了

Firefox的Firebug也是一个很不错的调试工具。

首先需要了解基本的Python语法,HTTP请求(post,get),详细教程请移步这里

模拟登录

首先贴出学校选课系统的主页(几年前的iframe嵌套风格,前端逼格太low没办法)

1469182285880选课主页.png

模拟登录是爬虫的里面很重要的一个环节。模拟登录一个站点时,首先要弄清网站的登录处理细节(内容,目的地…),这里通过Chrome开发者工具来抓取http数据包来分析该网站的登录流程。除此之外,我们还要分析抓到的post包的数据结构和header,要根据提交的数据结构和heander来构造自己的post数据和header。

我们要构造自己的HTTP数据包,并发送给指定url。我们通过urllib2等几个模块来实现request请求的发送和相应的接收。大部分网站登录时需要携带cookie,所以我们还必须设置cookie处理器来保证cookie。

这里我通过两种方法实现模拟登录,手动输入和cookie。

手动输入

这里先手动输入学号,密码和验证码进行模拟登陆。

点击登录,弹出输入框。

1467815644996模拟登陆.png

接着扒扒验证码的url。

1467816229586验证码.png

抓取正常登录下的http请求。

1467816040458模拟登陆审查元素1.png

可以看到浏览器以post方式向服务器提交了用户名(学号),密码和验证码。(密码都以明文方式发送而且走的是http,安全意识感人)

这里确保提交表单时和获取验证码使用了相同的cookie,否则输入验证码会一直报错。

捣鼓

首先创建一个cookie容器来存放登录验证码url时的cookie数据,通过用户的输入生成post表单数据,通过抓取的http请求构造heander,再以刚刚获取的cookiejar生成handler,最终生成一个opener对象,传递给open方法,即成功提交了post请求。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57import urllib2

import cookielib

import sys

import os

urne = raw_input('请输入学号: ')

pswd = raw_input('请输入密码: ')

reload(sys)

sys.setdefaultencoding("utf-8")

# 验证码地址和post地址

CaptchaUrl = "http://www.xxx.edu/ssfw/jwcaptcha.do"

PostUrl =="http://www.xxx.edu/ssfw/j_spring_ids_security_check"

# 将cookies绑定到一个opener cookie由cookielib自动管理

cookie = cookielib.CookieJar()

handler = urllib2.HTTPCookieProcessor(cookie)

opener = urllib2.build_opener(handler)

# 用openr访问验证码地址,获取cookie

picture = opener.open(CaptchaUrl).read()

# 保存验证码到本地

local = open('image.jpg', 'wb')

local.write(picture)

local.close()

# 打开保存的验证码图片 输入

os.startfile("image.jpg")

SecretCode = raw_input('请输入验证码: ')

# 根据抓包信息 构造表单

postData = {

'j_username':urne,

'j_password': pswd,

'validateCode': SecretCode,}

# 根据抓包信息 构造headers

headers = {

"Accept":"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",

"Accept-Encoding":"gzip, deflate",

"Accept-Language":"zh-CN,zh;q=0.8",

"Cache-Control":"max-age=0",

"Connection":"keep-alive",

"Content-Length":"59",

"Content-Type":"application/x-www-form-urlencoded",

"Upgrade-Insecure-Requests":"1",

"User-Agent":"Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.75 Safari/537.36",}

# 生成post数据 构造?key1=value1&key2=value2的形式

data = urllib.urlencode(postData)

#发送请求

request = urllib2.Request(PostUrl, data, headers)

response = opener.open(request)

Cookie自动输入

有时还是嫌手动输入太麻烦,而且选课系统不允许一个用户同时在多个地方登录,用上一种方法模拟登陆后原有的浏览器的cookie就失效了.

直接提取已登录成功的cookie岂不是更方便,而且可以脚本和浏览器同时登录而互不影响,cookie登录也是反反爬虫的惯用做法。

为了更方便地导出chrome中的cookie可以使用EditThisCookie(好多次看成eatthiscookie)

1469182753493editthiscookies.png

在浏览器中点击这款插件的图标,点击向右的按钮复制到剪贴板,这里我将其保存为cookie.txt,并且放置在和脚本相同的目录下。

1469182527535cookietxt.png

现在可以省掉输入用户名,密码和验证码的步骤了,一个cookie通通搞定。

1

2

3

4

5

6

7

8

9

10

11cookie_jar = cookielib.MozillaCookieJar()

cookies = open('cookies.txt').read()

for cookie in json.loads(cookies):

cookie_jar.set_cookie(cookielib.Cookie(version=0, name=cookie['name'], value=cookie['value'], port=None, port_specified=False, domain=cookie['domain'], domain_specified=False, domain_initial_dot=False, path=cookie['path'], path_specified=True, secure=cookie['secure'], expires=None, discard=True, comment=None, comment_url=None, rest={'HttpOnly': None}, rfc2109=False))

handler = urllib2.HTTPCookieProcessor(cookie_jar)

opener = urllib2.build_opener(handler)

request = urllib2.Request(PostUrl)

response = opener.open(request)

检测脚本是否登录成功登录成功

但是怎么知道脚本登录是否成功呢,一开始我的想法是:正常登录成功过后的response中的html内容中会含有姓名,班级等等一些信息,但是如果单纯正则表达式匹配,寻找DOM节点将变得相(gen)当(ben)复(bu)杂(hui),当然Python的第三方库也可以解析html,例如BeautifulSoup,功能很强大,但解析的速度很成问题,那有没有其他的办法呢。

于是我继续点击其他的按钮,同时观察http请求。

一会儿就发现规律了,每次点击触发http请求的元素时,客户端总是会发送一个get请求来获取登录状态,服务端返回一个json,在线为True,离线为False(简直像调用API一样方便)

选课请求分析

进入选课界面,写此文时正好赶上专业外通识课的选课时间,这个课是抢不完的,随便选一节课做试验。

1467815638185课程id.png

首先看看点击选课按钮后发生了些什么请求

1467815572724点击选课发生的相应.png

可以看到一共有三个http请求

1467815597665获取当前时间.png

可以看到第一项为获取服务器当前时间,返回一个json

1467815804719抢课请求1.png

第二项加了一个类似ID的参数,分析后可以知道是课程ID,获取这个ID应该可以从选课界面入手。

果不其然,对按钮审查元素过后就可以看到课程ID

1467815638185课程id.png

由于是测试的时候是公选课,所以还带有一个xkzy(选课志愿),不加默认为第一志愿,同意response返回一个json,第一个参数判断选课是否成功,如果成功,则第二个参数为当前时间,如果选课不成功,则返回失败原因。

1467815539877成功返回.png

抢课实战

  • 3
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值