吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 4884|回复: 36
收起左侧

[Python 转载] 【修改】监测12306并进行订票

[复制链接]
沧浪之水濯我心 发表于 2022-1-10 21:55
本帖最后由 沧浪之水濯我心 于 2022-1-10 22:02 编辑

因为买票需求,于是从网上找了一段代码Python实现12306自动抢火车票功能_python_脚本之家 (jb51.net),并进行了修改
原代码只能实现购票,我对代码进行了修改,增加了监测和抢票成功推送功能。
需要自行输入12306账号、密码,购买车次、时间、出发站、目的站、server酱key(Server酱·Turbo版 (ftqq.com)去申请)

经测试可成功购票,但有如下问题需要注意:
1.登录测试过多可能会导致滑块验证失败,可自行点击刷新,即可自动执行后续代码(懒得写刷新验证了,只要不是多次运行,一般不会有这个问题)
2.main()中,买票buy那一块,因为我是要抢票,等待时间设置为2,如果是监测,建议设置时间长一点,因为有可能被反爬
3.买票提交按钮可能会有bug,于是我在main中增加了一次选择来确保。但无论如何,进入提交页面你都会收到微信提示,为了保险,建议去看一下是否真的提交了,手动提交也不是不可以。
4.多人买票请在buy()函数下names里填入
5.代码中那么多**code,是我用来标记这段代码是否执行成功,如果没有成功就重复执行,如果code=0,代码没成功,再从头执行,gmcode和code感觉有点重复了,但是,管他呢,能运行就行了, 滑稽.jpg
6.我只是个业余程序猿,代码改的丑陋,我尽量写的通俗易懂了,大佬勿喷。

环境:(食用本代码需要一定的基础知识,新手估计挺难得)
python3
webdriver
以及一些库,我用pycharm,没有的库可以直接导入
还有,我觉得最主要的就是webdriver,自己有的话更好,配置的话可能需要很久时间,也挺麻烦的


代码如下:
[Python] 纯文本查看 复制代码
# -*- coding:utf-8 -*-
import json
import requests
import time
from captcha import *
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import wait
from selenium.webdriver.common.keys import Keys
from selenium.common.exceptions import NoSuchElementException
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.support import expected_conditions as EC




# 定义一系列code来确保每一步执行成功再进入下一步
global logincode, hkcode, yzcode, xpcode, cpcode, gmcode, code


# 初始化
def init_program():
    options = webdriver.ChromeOptions()
    options.add_argument("--disable-blink-features=AutomationControlled")
    browser = webdriver.Chrome(options=options)
    browser.maximize_window()

    return browser


# 登录12306
def login(browser):
    global logincode
    logincode = 0
    password = ''  # 登录12306的秘密
    username = ''  # 登录12306的账号
    login_url = 'https://kyfw.12306.cn/otn/resources/login.html'
    # ticket_url = 'https://kyfw.12306.cn/otn/leftTicket/init'
    try:
        browser.get(login_url)
        time.sleep(0.5)
        wait.WebDriverWait(browser, 5).until(EC.element_to_be_clickable((By.CLASS_NAME, 'login-hd-code'))).click()
        input_name = browser.find_element_by_id('J-userName')
        input_pd = browser.find_element_by_id('J-password')
        input_name.send_keys(username)
        input_pd.send_keys(password)
        login = browser.find_element_by_id('J-login')
        login.click()
        logincode = 1
    except Exception as e:
        logincode = 0
        print(e)

    


# 拉动滑块验证
def huakuai(browser):
    global hkcode
    hkcode = 0
    try:
        browser.implicitly_wait(5)
        print('=====开始处理滑动验证码=====')
        track = [300, 400, 500]
        for i in track:
            try:
                btn = browser.find_element_by_xpath('//*[@id="nc_1__scale_text"]/span')
                ActionChains(browser).drag_and_drop_by_offset(btn, i, 0).perform()
                hkcode = 1
            except:
                time.sleep(2)
    except Exception as e:
        hkcode = 0
        print(e)
    

# 疫情特殊要求
def yiqingyaoqiu(browser):
    global yzcode
    yzcode = 0
    try:
        browser.implicitly_wait(5)
        try:
            browser.find_element_by_xpath('/html/body/div[4]/div[2]/div[3]/a').click()
            yzcode = 1
        except:
            try:
                browser.find_element_by_xpath('/html/body/div[2]/div[7]/div[2]/div[3]/a').click()
                yzcode = 1
            except:
                yzcode = 0
        finally:
            time.sleep(2)
    except Exception as e:
        yzcode = 0
        print(e)
    


# 进入买票页面
def enterbuy(browser):
    global xpcode
    xpcode = 0
    try:
        browser.find_element_by_xpath('//*[@id="J-chepiao"]/a').click()
        browser.find_element_by_xpath('//*[@id="megamenu-3"]/div[1]/ul/li[1]/a').click()
        browser.find_element_by_xpath('//*[@id="qd_closeDefaultWarningWindowDialog_id"]').click()
        xpcode = 1
    except Exception as e:
        print(e)
        xpcode = 0
    


# 将出发地、目的地、出发日期填进去
def input_info(browser):
    global cpcode
    cpcode = 0

    date = '2022-01-24'  # 填写购票日期
    start_station = ''  # 购票出发站,例如南京南
    end_station = ''  # 购票目的站
    try:
        print('=====开始买票=====')
        from_station = browser.find_element_by_xpath('//*[@id="fromStationText"]')
        from_station.send_keys(Keys.ENTER)
        from_station.send_keys(Keys.CONTROL, 'a')
        from_station.send_keys(start_station, Keys.ENTER)
        browser.implicitly_wait(5)
        to_station = browser.find_element_by_xpath('//*[@id="toStationText"]')
        to_station.send_keys(Keys.ENTER)
        to_station.send_keys(Keys.CONTROL, 'a')
        to_station.send_keys(end_station, Keys.ENTER)
        browser.implicitly_wait(5)
        start_date = browser.find_element_by_xpath('//*[@id="train_date"]')
        start_date.send_keys(Keys.ENTER)
        start_date.send_keys(Keys.CONTROL, 'a')
        start_date.send_keys(Keys.CONTROL, 'x')
        start_date.send_keys(date, Keys.ENTER)
        browser.implicitly_wait(5)
        wait.WebDriverWait(browser, 3).until(EC.element_to_be_clickable((By.ID, 'query_ticket'))).click()
        cpcode = 1
    except Exception as e:
        print(e)
        cpcode = 0




# 依次查找trains中的车次是否有票,有的话点击购买
def buy(browser):
    global gmcode, code
    gmcode = 0
    code = 0
    purpose = 'ADULT'  # 购买成人票,如果是学生票,需调整代码
    names = ['']  # 填写购票人姓名,需要在你的乘车人管理里有的
    trains = []  # 你想买的班次,例如'D666',  'G666'
    browser.implicitly_wait(5)
    try:
        trList = browser.find_elements_by_xpath(".//tbody[@id='queryLeftTable']/tr[not(@datatran)]")
        for tr in trList:
            trainNum = tr.find_element_by_class_name("number").text
            if trainNum in trains:
                leftTicket = tr.find_element_by_xpath(".//td[4]").text
                print('leftTicket', leftTicket)
                if leftTicket == '有' or leftTicket.isdigit():
                    orderBtn = tr.find_element_by_class_name("btn72")
                    orderBtn.click()
                    browser.implicitly_wait(5)
                    passengerLabels = browser.find_elements_by_xpath(".//ul[@id='normal_passenger_id']/li/label")
                    for passengerLabel in passengerLabels:
                        name = passengerLabel.text
                        if name in names:
                            passengerLabel.click()
                    browser.implicitly_wait(20)
                    # 获取提交按钮
                    submitBtn = browser.find_element_by_id("submitOrder_id")
                    submitBtn.click()
                    browser.implicitly_wait(20)
                    confirmBtn = browser.find_element_by_id("qr_submit_id")
                    confirmBtn.click()
                    time.sleep(2)
                    browser.implicitly_wait(20)
                    confirmBtn = browser.find_element_by_id("qr_submit_id")
                    confirmBtn.click()
                    code = 1
                    gmcode = 1
                    break

    except Exception as e:
        print(e)
        gmcode = 0
    


def tuisong():
    api = "https://sctapi.ftqq.com/*****.send" #*****替换成你的微信server酱的key,可以实现购票成功推送,然后你就自己去12306付款

    title = '购买成功'

    data = {
        "text": title
    }
    req = requests.post(api, data=data)


if __name__ == "__main__":
    global logincode, yzcode, hkcode, xpcode, cpcode, gmcode, code
    code = 0
    logincode = 0
    yzcode = 0
    hkcode = 0
    xpcode = 0
    cpcode = 0
    gmcode = 0
    browser = init_program()
    while code == 0:
        while logincode == 0:
            login(browser)
            print('logincode:', logincode)

        while hkcode == 0:
            huakuai(browser)
            print('hkcode:', hkcode)

        while yzcode == 0:
            yiqingyaoqiu(browser)
            print('yzcode:', yzcode)

        while xpcode == 0:
            enterbuy(browser)
            print('xpcode:', xpcode)

        while cpcode == 0:
            input_info(browser)
            input_info(browser)#经测试,一次有可能不成功,我直接两次提交
            print('cpcode:', cpcode)

        while gmcode == 0:
            buy(browser)
            print('gmcode:', gmcode)
            print('code:', code)
            if gmcode == 0:
                browser.refresh()
                time.sleep(2)
                browser.find_element_by_xpath('//*[@id="qd_closeDefaultWarningWindowDialog_id"]').click()
                input_info(browser)
                input_info(browser)
            else:
                try:
                    print('tijiao')
                    confirmBtn = browser.find_element_by_id("qr_submit_id")
                    browser.implicitly_wait(20)
                    time.sleep(3)
                    confirmBtn.click()
                except:pass



        if code == 1:
            tuisong()
            break

免费评分

参与人数 3吾爱币 +9 热心值 +3 收起 理由
寒墨轩 + 2 + 1 热心回复!
苏紫方璇 + 7 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
huiye123 + 1 当第一个评论 不过分吧。哈哈哈哈

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

brightwill 发表于 2022-1-11 11:45
browser.find_element_by_xpath('//*[@id="qd_closeDefaultWarningWindowDialog_id"]').click()
这个模态框得用异常捕获去执行,不然会报错无法往下运行
执行两次点击查询按钮就不用再执行两次input_info方法才生效
wait.WebDriverWait(browser, 3).until(EC.element_to_be_clickable((By.ID, 'query_ticket'))).click()
挺不错的  支持楼主,我也是个小白
 楼主| 沧浪之水濯我心 发表于 2022-1-12 19:05
daymissed 发表于 2022-1-11 15:31
大佬,我测试了一下,在有票情况下也无法抢票,不知啥情况.一直是这样:yzcode: 0
yzcode: 0
yzcode: 0

我跟你说怎么解决,应该是卡在有个疫情特殊要求的界面,需要点确认,12306对这个确认的html做了动态化处理,我自己测试到2个,你右击确认按钮,检查,选择复制菜单栏下的完整的xPath拷贝到# 疫情特殊要求代码块下的browser.find_element_by_xpath('/html/body/div[2]/div[7]/div[2]/div[3]/a').click()
jets2006 发表于 2022-1-10 22:04
 楼主| 沧浪之水濯我心 发表于 2022-1-10 22:05
jets2006 发表于 2022-1-10 22:04
哥,你就好人做到底吧!!

我咋了,啥好人做到底
71q3M5cT9a 发表于 2022-1-10 22:06
这个就是加了一些定时查询的功能,但是会不会引起12306对频繁请求的IP进行封锁呢
 楼主| 沧浪之水濯我心 发表于 2022-1-10 22:08
71q3M5cT9a 发表于 2022-1-10 22:06
这个就是加了一些定时查询的功能,但是会不会引起12306对频繁请求的IP进行封锁呢

我自己测试了几十次,遇到了一次页面无法加载,等待了几分钟重新运行又可以了。主要是12306已经很难了,不想给他增加负担....能买到票我就满足了
 楼主| 沧浪之水濯我心 发表于 2022-1-10 22:13
71q3M5cT9a 发表于 2022-1-10 22:06
这个就是加了一些定时查询的功能,但是会不会引起12306对频繁请求的IP进行封锁呢

主要是我也没测试出反爬机制,如果是基于ip,买点代{过}{滤}理池应该就可以了吧
LonelyFish 发表于 2022-1-10 22:25
71q3M5cT9a 发表于 2022-1-10 22:06
这个就是加了一些定时查询的功能,但是会不会引起12306对频繁请求的IP进行封锁呢

应该没事,12306网站本身就有定时自动刷新的功能
ych13846701169 发表于 2022-1-10 23:09
好啊,就是学不会呀
richardzxq 发表于 2022-1-11 06:08
谢谢试试看!
头像被屏蔽
tl;dr 发表于 2022-1-11 07:01
提示: 作者被禁止或删除 内容自动屏蔽
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-25 06:40

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表