python编写12306窗体抢票软件(二)
python编写12306窗体抢票软件(二)
本文这次介绍如何获取12306网站的验证码并登陆。
1 获取验证码
12306它是一个服务器,每次我们访问它都是以客户端的方式去向它索取信息。
建议用谷歌浏览器,按F12可以看到你发出去的请求和返回来的数据包,这样更好的理解这个过程。
上图:
选择Network,最左边就是打开这个网页所进行的每个过程,找到获取验证码的这一条,Headers,就能看到Request URL,这个就是你请求的链接,仔细看左边的流程,你会看到image,这个就是网站给你返回来的验证码图片,我们首先就是要获取到这个图片。
当你选择了验证码图片后,点击登录时,它会先检查你验证码对不对,看answer数据,这是两个坐标,整个验证码图片 有8个小图片,你只要点击的坐标范围是对的,就校验通过了。
所以我们需要输入的答案就是坐标值。
2.了解session
我们去访问一个网站,就是创建了一个session请求,后面我们所有进行的操作都是基于这个session去完成的,被访问的网站怎么知道你是第一次访问还是之前就访问过的呢,这通过cookies来完成,这个相当于服务器(也就是网站)给了你一把钥匙,之后你访问一直带着这个钥匙,他就知道你进行过什么操作了,这个也是之后非常重要的一步,关系到能否记住你的登录状态。
#创建一个session
req = requests.Session()
req.verify=False
headers = {
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36',
'Referer':'https://kyfw.12306.cn/otn/passport?redirect=/otn/login/userLogin'
}
之后每次访问都用这个就自带cookies
里面这个url就是我们刚才F12我们看到的请求验证码那个链接,response就是返回的结果,里面带着验证码图片。我们把它存在本地,再通过窗体QLable这个也可以显示图片,把验证码显示出来。
def get_img(self):
#验证码
response = req.get('https://kyfw.12306.cn/passport/captcha/captcha-image?login_site=E&module=login&rand=sjrand')
with open('img.jpg', 'wb') as f:
f.write(response.content)
这8个坐标对应8张图片的大概中心位置,
[‘35,35’, ‘105,35’, ‘175,35’, ‘245,35’,
‘35,105’, ‘105,105’, ‘175,105’, ‘245,105’]
然后我们去请求的链接中data中带上我们的答案,也就是坐标(12306登录是先验证你的验证码对不对,再去验证你的用户名和密码)如果返回值是4 我们再进行用户名和密码的请求
Pic_addr = picnum.split(',')
check_addr = ['35,35', '105,35', '175,35', '245,35', '35,105', '105,105', '175,105', '245,105']
List = []
for item in Pic_addr:
List.append(check_addr[int(item)-1])
Answer = ','.join(List)
checkUrl = "https://kyfw.12306.cn/passport/captcha/captcha-check"
data = {
'login_site': 'E',
'rand': 'sjrand',
'answer': Answer # 验证码对应的坐标
}
cont = req.post(url=checkUrl, data=data, headers=headers)
dic = loads((cont.content).decode())
code = dic['result_code']
# 验证结果
4:成功
5:验证失败
7:过期
8:没有带cookies
if str(code) == '4':
print('success')
return True
else:
print('fail')
return False
3 登录
loginUrl = “https://kyfw.12306.cn/passport/web/login”
访问这个需要带上你的用户名和密码
代码:
def login(self,username,password):
userName = username
pwd = password
loginUrl = "https://kyfw.12306.cn/passport/web/login"
data = {
'username': userName,
'password': pwd,
'appid': 'otn'
}
response = req.post(url=loginUrl, data=data, headers=headers)
谨记:这里解析response它会返回登录成功,但这并不是真正的登录成功,还需进行下面两次请求才是真正登录上了,它会返回你的用户名。
def login(self,username,password):
userName = username
pwd = password
loginUrl = "https://kyfw.12306.cn/passport/web/login"
data = {
'username': userName,
'password': pwd,
'appid': 'otn'
}
response = req.post(url=loginUrl, data=data, headers=headers)
data ={
"appid": "otn"
}
Authurl = "https://kyfw.12306.cn/passport/web/auth/uamtk"
response = req.post(url = Authurl , headers=headers, data=data)
if response.status_code == 200:
result = loads(response.text)
#print(result.get("result_message"))
newapptk = result.get("newapptk")
data = {
"tk": newapptk
}
clienturl = "https://kyfw.12306.cn/otn/uamauthclient"
response = req.post(url =clienturl , headers=headers, data=data)
if response.status_code == 200:
print(response.text)
dic = loads((response.content).decode("utf-8"))
mes = dic['result_message']
if mes == u'验证通过':
self.Save_cookies()
checkuser_url = 'https://kyfw.12306.cn/otn/login/checkUser'
response = req.get(url=checkuser_url, headers=headers)
response = response.json()['data']['flag']
if response == True:
print('验证通过')
return True
elif response == False:
print('验证失败')
else:
return False
4.保存登录状态
如果上面都成功的话,就真的登陆上了。但是大家都知道平常我们用浏览器登录12306的时候,一段时间内是不会让你登录再登录的,这是因为我们在用浏览器访问的时候,cookies已经被保存在本地了,所以我们也可以这样做,来保存我们的登录状态。
def Save_cookies(self):
_cookies = req.cookies.get_dict()
cookieStr = json.dumps(_cookies)
with open('./cookies.txt', 'w') as f:
f.write(cookieStr)
def Get_cookies(self):
try:
with open('./cookies.txt', 'r') as f:
_cookies = json.load(f)
req.cookies = requests.utils.cookiejar_from_dict(_cookies)
except:
self.get_img()
这样就可以直接登录了,也就是我上文中界面有个直接登录按键的作用。
下次我会写获取12306车次信息,联系人等,如果写的多的话应该能写完~~请大家多多关注哈