python实现12306抢票
先附上一张图片
通过手动输入图片验证码的方式实现自动登陆12306进行查票选择购买车次时间,自动进行余票查询,最后直到购票成功。
首先我们打开12306的网址,打开f12开发者工具点击network,点击选择账号密码登陆,我们可以看到
我们清空所有所有加载,然后点击图片验证码右上方的刷新,这个时候我们可以明显的看到有一个图片的请求进行了加载,我们点击查看返回的数据
很明显的发现这张图片就是返回给我们验证码,接下来我们去查看headers发现图片请求URL是这样的一串东西,很明显,这不是我们需要的,这个时候我们查看加载的请求,发现每次我们刷新图片的时候,实际上是先请求了另外一个URL然后才生成的图片,
我们查看另外一个请求,发现它返回的数据我们复制URL打开,发现图片生成的加密地址,于是我们就找到了图片,加下来我们只需要把图片保留到本地打开就可以完成了我们基本到目的
这里先贴出部分代码
# 为了防止ssl出现问题
ssl._create_default_https_context = ssl._create_unverified_context
# 以下进行登陆操作
# 建立cookie处理
cjar = http.cookiejar.CookieJar()
opener = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(cjar))
urllib.request.install_opener(opener)
# 以下进入自动登录部分
loginurl = "https://kyfw.12306.cn/otn/login/init#"
req0 = urllib.request.Request(loginurl)
req0.add_header('User-Agent', 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, lik\
e Gecko) Chrome/38.0.2125.122 Safari/537.36 SE 2.X MetaSr 1.0')
req0data = urllib.request.urlopen(req0).read().decode("utf-8", "ignore")
yzmurl = "https://kyfw.12306.cn/passport/captcha/captcha-image?login_site=E&module=login&rand=sjrand"
while True:
urllib.request.urlretrieve(yzmurl,"/Users/wangfukang/Desktop/project_scrapy_my/scrapy_file/12306_yzm.png")
yzm = input("请输入验证码,输入第几张图片即可:")
if (yzm != "re"):
break```
这里我们主要着重介绍一个方法urllib.request.urlretrieve,它的作用主要是将远程数据保存在本地,这里不详细讲解。接下来我们再次清空请求,然后点击图片进行登陆,发现每一次我们在提交的时候都会进行校验是否正确,我们查看携带的参数,发现![在这里插入图片描述](https://img-blog.csdnimg.cn/20190110154405181.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQxNzE4MTU1,size_16,color_FFFFFF,t_70)
有个特殊的参数,多次点击不同位置,发现它的值不同,其他参数固定不变,我们猜测这个就是我们用鼠标进行点击的位置,我们查看element,发现图片整个长度为![在这里插入图片描述](https://img-blog.csdnimg.cn/20190110154621389.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQxNzE4MTU1,size_16,color_FFFFFF,t_70)
于是我们多次调试,发现这个猜测是对对,于是我们按照每张图片,设置一个图片点击位置,来标记我们每次提交的对应参数,
#通过逗号分隔多张图片
allpic = yzm.split(’,’)
def getxy(pic):
if (pic == 1):
xy = (35, 45)
if (pic == 2):
xy = (112, 45)
if (pic == 3):
xy = (173, 45)
if (pic == 4):
xy = (253, 45)
if (pic == 5):
xy = (35, 114)
if (pic == 6):
xy = (112, 114)
if (pic == 7):
xy = (173, 114)
if (pic == 8):
xy = (253, 114)
return xy
如上,这样我们就可以确定每一张图片的位置,方便我们在本地查看验证码的时候,只需要输入对应数字就可以来,接下来我们就可以携带账号密码来请求登陆了,把剩余代码先贴出来,欢迎大家留言进行交流
allpicpos = “”
for i in allpic:
thisxy = getxy(int(i))
for j in thisxy:
allpicpos = allpicpos + str(j) + “,”
allpicpos2 = re.compile("(.*?).$").findall(allpicpos)[0]
print(allpicpos2)
post验证码验证
yzmposturl = “https://kyfw.12306.cn/passport/captcha/captcha-check”
yzmpostdata = urllib.parse.urlencode({
“answer”: allpicpos2,
“rand”: “sjrand”,
“login_site”: “E”,
}).encode(‘utf-8’)
req1 = urllib.request.Request(yzmposturl, yzmpostdata)
req1.add_header(‘User-Agent’, ‘Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.122 Safari/537.36 SE 2.X MetaSr 1.0’)
req1data = urllib.request.urlopen(req1).read().decode(“utf-8”, “ignore”)
post账号密码验证
loginposturl = “https://kyfw.12306.cn/passport/web/login”
loginpostdata = urllib.parse.urlencod