用python实现12306登录、查票(小白都一看就懂的)

       看到很多人对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)

登录和查票就到此结束了,如果有什么疑问可以留言哈

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值