看到很多人对12306抢票有着非常大的兴趣,所以我就试了下登录,查票,购买还没实现,并且我的方法也不是很理想,推荐给小白学习,并且我也是用最易懂的代码来写,所以说如果你是一位python爬虫小白的话,那这篇文章或许会帮到你,干货满满@
2021-02-23日更新:
各位小伙伴,是不是查询余票都特别困难了?12306升级后,直接使用开发者工具抓包得到的ajax链接直接照搬不管用了,除非是将原cookies加入头文件中,否则访问永远都是提示错误,其实这个很好解决
但是cookie有有效期,过一段时间就无法使用了,其实这也是一个反爬措施,我走了点捷径,发现这样也行,所以,查票目前还是很简单的
1.使用requests模块的session函数,记录下当前的操作一直都是一个浏览器
2.先访问查询页面的前一个页面
3.再访问ajax查询接口
来看看我的代码吧:
import requests # 使用session记录当前是同一个会话(通俗的说就是所有的操作都在同一个浏览器中操作) request = requests.session() # 查询页的前一个页面 url_1 = "https://kyfw.12306.cn/otn/leftTicket/init?linktypeid=dc&fs=%E6%B7%B1%E5%9C%B3," \ "SZQ&ts=%E6%88%90%E9%83%BD,CDW&date=2021-02-27&flag=N,N,Y" # ajax查询接口 url = "https://kyfw.12306.cn/otn/leftTicket/queryZ?leftTicketDTO.train_date=2021-02-27&leftTicketDTO.from_station=SZQ&leftTicketDTO.to_station=CDW&purpose_codes=ADULT" # 这里列出了此接口的参数,因为网址已经包含这些信息了,后期就不用拼接了 from_data = { 'leftTicketDTO.train_date': '2021-02-23', 'leftTicketDTO.from_station': 'SZQ', 'leftTicketDTO.to_station': 'CDW', 'purpose_codes': 'ADULT', } # 这个记得加上哦 header = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36' } # 先访问前一个页面 req = request.get(url_1, headers=header) # 再访问接口 req_3 = request.get(url, headers=header) # 成功! print(req_3.text)
讯享网
这样一来,系统就会认为你是从前一个页面过来的,于是成功绕过这个反爬措施
2021-02-24日更新:获取所有12306车站编码信息,格式化数据成字典类型(变成字典了就能随便存到哪了,mysql、mongodb、elasticsearch等等)
以下是代码:
讯享网# version版本信息,默认是我写这块代码的最新版本,我测试过,不加版本号也是可以获取到的 def init_station_code(version=1.9186): # 车站编码网址 get_station_url = "https://kyfw.12306.cn/otn/resources/js/framework/station_name.js" station_msg_req = requests.get(url=get_station_url, headers=headers, params={"station_version": version}) # 正则提取“|北京|VPA|”格式的内容 d = re.findall("^|[\u4e00-\u9fa5]{2,5}[|][A-Z]{2,5}|$", station_msg_req.text) # 将车站名称和车站编码变成字典格式 station_msg = [{"station_name": x.split("|")[0], "station_code": x.split("|")[1]} for x in d[1: -1]] # 剩余的你想怎么存就怎么存 print(station_msg)
注:所有代码在python3.6环境下编写,请留意版本区别
查票:
2021-02-24日更新:查票信息更加详细化
如果你没有登录,查票也是可以查的,同时按照逻辑来说的话,你也是先看有没有票再去考虑登录购买吧?你也许会问为什么你知道data[3]代表车次,data[*]代表,同样,我也是通过开发者工具抓包知道的,抓到数据之后,进行一些简单分析即可知道
代码同样非常简单:
# 查票,参数:from_station:起始站, to_station:终点站, train_date:乘车时间 def find_train_tickets(from_station, to_station, train_date): url_1 = "https://kyfw.12306.cn/otn/leftTicket/init?linktypeid=dc&fs=%E6%B7%B1%E5%9C%B3,SZQ&ts=%E6%88%90%E9%83%BD,CDW&date=2021-02-27&flag=N,N,Y" url = "https://kyfw.12306.cn/otn/leftTicket/queryZ" from_data = { 'leftTicketDTO.train_date': train_date, 'leftTicketDTO.from_station': from_station, 'leftTicketDTO.to_station': to_station, 'purpose_codes': 'ADULT', } request.get(url_1, headers=headers) train_tickets_req = request.get(url, headers=headers, params=from_data) train_tickets_msg = train_tickets_req.json() if train_tickets_msg["httpstatus"] == 200: return train_tickets_msg["data"]["result"] else: return False # 官网上能显示的我都整理出来了,比很多博主都详细 for i in check(): gf = i.split("|") msg = {"车辆编号": gf[2], "车次": gf[3], "出发站": gf[6], "到达站": gf[7], "出发时间": gf[8], "到达时间": gf[9], "历时": gf[10], "乘车时间": gf[13], "商务座/特等座": gf[32] or "--", "一等座": gf[31] or "--", "二等座/二等包座": gf[30] or "--", "高级软卧": gf[21] or "--", "软卧/一等卧": gf[23] or "--", "动卧": gf[33] or "--", "硬卧/二等卧": gf[28] or "--", "软座": gf[24] or "--", "硬座": gf[29] or "--", "无座": gf[26] or "--", "其他": gf[22] or "--"}
再来看看登录吧:
2021-02-26日更新:登录信息优化,同时代码也比之前更简洁
现在图片需要base64转码了,我也用过打码平台的验证码校验,发现还挺准的,如果你不想手动输入验证码坐标,就用打码平台吧
get_v_code_url, check_v_code_url, login_url 分别代表验证码获取地址,校验验证码地址,登录地址,经测试发现,验证码校验方式由以前的POST方式变成了get了,这点需要注意,同时发现,如果验证码校验没有通过,是不会访问login_url的,所以必须要先验证完验证码,
最后就是登录了,经过多次尝试,单提交用户名密码这些信息还不够,现在正在找方法,先还是把我目前写的代码附上吧:
讯享网def login(): get_v_code_url = "https://kyfw.12306.cn/passport/captcha/captcha-image64" check_v_code_url = "https://kyfw.12306.cn/passport/captcha/captcha-check" login_url = "https://kyfw.12306.cn/passport/web/login" # 步骤-:将base64编码的图片保存下来,手动输入验证码位置 req_v_code = request.get(url=get_v_code_url) with open("code.jpg", "wb") as f: f.write(base64.b64decode(req_v_code.json()['image'])) # 各验证码参考位置: code_answer = { 1: (37, 47), 2: (121, 41), 3: (193, 45), 4: (268, 46), 5: (42, 111), 6: (117, 110), 7: (188, 113), 8: (263, 114), } v_code_ad = input("请输入验证码位置,多个位置用逗号隔开:") data_check = { 'login_site': 'E', # 固定的 'rand': 'sjrand', # 固定的 'answer': v_code_ad # 验证码对应的坐标 } # 步骤二:校验验证码信息 req_check_v_code = request.get(url=check_v_code_url, params=data_check).json() # 步骤三:登录网站 if response.json()["result_code"] == "4": username = str(input("请输入用户名:")) userpassword = str(input("请输入密码:")) data_2 = { 'appid':'otn', 'password': userpassword, 'username': username } response = request.post(login_url, data=data_2) print(response.text)
登录和查票就到此结束了,如果有什么疑问可以留言哈

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/43029.html