使用Python模拟登陆12306并全自动下单

最近一段时间一直在研究用Python模拟登陆12306网站并自动刷票下单,经过一段时间的摸索,终于完成了代码,实现了12306刷票的功能。

话不多说,先给大伙儿看看成果。我录制了一段时间,展示了自动刷票下单的全过程,实际效果可以移步这里观看:

Python模拟登陆12306并自动下单

可以看到,只需要输入车次和乘车人姓名,代码能自动下单预定,基本达到了我预想的效果。接下来我就一步一步给大家详细讲解一下这个模拟登陆并自动下单的过程。
首先是登陆。通过抓包我们发现,12306的登陆是分两步的,第一步是获取验证码并验证验证码输入是否正确,输入正确接下来才会验证用户名和密码,全都验证通过方才能成功登陆。我们的第1步是获取验证码。
通过抓包,我们可以知道12306获取验证码的地址是:https://kyfw.12306.cn/passport/captcha/captcha-image?login_site=E&module=login&rand=sjrand&0.8030393410546426,获取方式是GET,我们首先导入requests库,建立一个会话。
#!/usr/bin/env python
# -*- coding:utf-8 -*-

import requests
session = requests.session()
然后设置请求验证码网址,获得验证码。这里为了确保验证码出错了程序能自动重新获取验证码,我们使用一个While循环。另外,为了确保验证码能看清晰,我们将验证码图片保存到本地来。
captchaurl = 'https://kyfw.12306.cn/passport/captcha/captcha-image?login_site=E&module=login&rand=sjrand&0.8030393410546426'
While True:
    captchapage = session.get(captchaurl)
    with open('code.png','wb') as fn:
        fn.write(captchapage.content)
        fn.close()
然后我们构造一个字典,将验证码的位置信息放进去,这样方便我们在登陆的时候只需要输入验证码序号即可实现验证。
code = {
        '1': '40,40',
        '2': '110,40',
        '3': '180,40',
        '4': '260,40',
        '5': '40,120',
        '6': '110,120',
        '7': '180,120',
        '8': '260,120'
    }
这是我通过摸索确定的验证码的位置信息。这里有一个难题,符合条件的验证码的图片张数是不确定的,有可能是1张,2张,3张甚至更多,我们怎么处理呢?通过切片和添加把符合条件的位置信息组合成一个字符串。
 captchacode = input('请输入验证码序号:')  #用户手动输入验证码序号
temp = captchacode.split(',') #将输入的序号以','号分隔,组成一个输入的数字的列表
tempcode = ''  #构建一个空字符串
for i in temp:  # 对验证码序号列表进行遍历
    tempcode += code[i] + ',' #将每个验证码序号对应的位置信息添加到字符串中,并加上','号
finalcode = tempcode.rstrip(',')   #将最后一个','号去掉,构成一个位置信息的字符串
然后我们将这些信息POST给验证码验证网址进行验证,代码如下:
captchadata = {
    'answer': finalcode,
    'login_site': 'E',
    'rand': 'sjrand'
    }
captchaheaders = {
    'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36',
    'Referer':'https://kyfw.12306.cn/otn/login/init'
}
captchaurl = 'https://kyfw.12306.cn/passport/captcha/captcha-check'
captchapage = session.post(captchaurl,data=captchadata,headers=captchaheaders,verify=False)  #注意关掉SSL验证   
然后我们对返回的页面进行解析,得到验证的结果。
passmess = json.loads(passpage.text)
if passmess['result_code'] == '4': #4代表成功,5代表验证码错误,8代表验证信息为空
    print(passmess['result_message'])
else:
    print('验证失败,请重新输入')
    continue #重新进行验证
验证码验证成功后就需要进行登陆,因为是验证成功之后紧接着进行的,我们把如下代码放到if条件语句之后,完整代码如下:   
passmess = json.loads(passpage.text)
if passmess['result_code'] == '4':
    print(passmess['result_message'])

    loginurl = 'https://kyfw.12306.cn/passport/web/login'
    logindata = {
        'username':'用户名',
        'password':'密码',
        'appid':'otn'
    }
    loginpage = session.post(loginurl,data=logindata,headers=passheaders,verify=False)
    loginmess = json.loads(loginpage.text)
    print(loginmess['result_message'])
    break
else:
    print('验证失败,请重新输入')
    continue
这样就实现了模拟登陆。当然,在这里你也可以对登陆的结果进行判断,主要是看用户名和密码是否正确,这个判断也可以先在浏览器中做好,确保写入程序的用户名和密码是正确的。
(未完待续,有空再更)

你可能感兴趣的:(python)