当前位置:首页 > 渗透测试 > 正文内容

python爬虫12306抢票(12306网上抢票软件)

访客3年前 (2022-01-30)渗透测试987

目录

一、效果展示

二、代码详解

1 导入库

2 确定好购票基本信息

3 登录12306

4 模拟滑动滑块

5 处理疫情特殊要求

6 点击购票并填写出发地、目的地、出发时间

7 锁定车票

三、实现监控购买

注意

环境

代码

大家有没有这种感觉,一到国庆、春节这种长假,抢火车票就非常困难?各大互联网公司都推出抢票服务,只要加钱给服务费就可以增加抢到票的几率。有些火车票代售网点和一些加速买票软件,说你只要给100元服务费就可以优先帮忙抢到票。

本文和你一起探索抢票软件背后的原理。

私信小编01即可获取大量Python学习资源

一、效果展示

在正式进入代码讲解之前,先来看下本文的实现效果。

如果不是为了演示效果,直接在最后确定阶段加一个延时点击确定,应该不到45秒可以锁定一张票,只要在30分钟之内付款即可。

二、代码详解

本小节会详细解锁抢票软件是如何模拟登录网站,进行自动买票的。为了更清晰地给大家展示,部分代码没有写成函数,直接裸代码运行,让需要买票的朋友可以自己应用软件进行购票。

1 导入库

首先导入本文需要加载的库,如果你有些库还没有安装,导致运行代码时报错,可以在Anaconda Prompt中用pip方法安装。

import json
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
#导入库

2 确定好购票基本信息

导入库后,在python代码中填写你购票的基本信息。

purpose = 'ADULT'               #购买成人票,如果是学生票,需调整代码
names = ['谢朝阳']              #填写购票人姓名
date = '2021-09-21'             #填写购票日期
start_station = '深圳'          #购票出发站
end_station = '长沙南'          #购票目的站
password = '11234567xyz'        #登录12306的秘密
username ='xiezhaoyang122700'   #登录12306的账号
trains = ['G1004'%2c 'G80'%2c 'G6028'%2c 'G6182'%2c 'G6016']  #你想买的班次
#填写基本信息

本文预订的是2021年9月21日从深圳到长沙南的高铁票,你可以根据自己的实际需要进行调整。由于有些班次的时间过早或过晚,买了也很不方便,所以可以在trains中挑选出你满意的班次进行购票。在这里需要提醒大家,我之前在尝试代码时碰到的坑,那就是时间中如果有个位数要在前面填0。比如2021年9月2日,你在填写购票日期date时要写成’2021-09-02’,否则在运行代码时日期总是填不进去。

3 登录12306

确定好购票的基本信息后,就可以应用python模拟登录12306了,代码如下:

options = webdriver.ChromeOptions
options.add_argument("--disable-blink-features=AutomationControlled")  
browser = webdriver.Chrome(options=options)
browser.maximize_window
login_url = 'https://kyfw.12306.cn/otn/resources/login.html'
#ticket_url = 'https://kyfw.12306.cn/otn/leftTicket/init'
browser.get(login_url)
time.sleep(0.5)
wait.WebDriverWait(browser%2c 5).until(EC.element_to_be_clickable((By.CLASS_NAME%2c'login-hd-account'))).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
#登录12306

整体思路是:

1.应用python模拟调用google浏览器;

2.输入12306网址;

3.等网页加载完全后点击账户密码登录;

4.找到账号密码的id,把账户密码信息填充进去;

5.找到登录id,模拟点击登录按钮。

在这一小节中要注意两个点。

一、要在python安装目录中放和google版本匹配的chromedriver,供python调用。

二、要学会填写账户密码信息的id。

首先,在google浏览器中输入12306登录网址:

中国铁路12306

接着点击账户密码登录,会出现如下界面:

然后点击红框中的三个点,找到更多工具,点击开发者工具,会出现如下界面:

点击红框中的箭头,把鼠标移动到账户框上去,就会出现如下界面:

右边变灰的框里就会出现对应的id,点击账号框,再把鼠标移动到右边变灰的字符上去,点击右键,会出现copy element的选项,复制下来即可。

<input type="text" class="input" id="J-userName" placeholder="用户名/邮箱/手机号" style="height: 44px; line-height: 44px; outline: black 0px;" aria-label="请输入用户名/邮箱/手机号" title="请输入用户名/邮箱/手机号">

发现了吗?源代码input_name中要填写的
browser.find_element_by_id(‘J-userName’)内容,即为id=”J-userName”中的信息。

4 模拟滑动滑块

输入完用户名和密码,点击立即登录后,会出现如下滑块验证要求。

运行如下代码即可拖动滑块进行验证。

browser.implicitly_wait(5)
print('=====开始处理滑动验证码=====')
track = [300%2c 400%2c 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%2ci%2c0).perform
    except:
        time.sleep(2)  
#拉动滑块验证

其中,browser.implicitly_wait(5)表示隐性等待5秒,track中放的是滑块拉动的距离。

5 处理疫情特殊要求

完成滑块验证要求后,会出现如下疫情特殊要求提示:

用如下代码点击确认即可。

 browser.implicitly_wait(5)
browser.find_element_by_xpath('/html/body/div[5]/div[2]/div[3]/a').click
time.sleep(2)  
#疫情特殊要求

browser.find_element_by_xpath和id的区别是,在右键复制时要copy XPath或copy full XPath。

6 点击购票并填写出发地、目的地、出发时间

接下来是选择买票,并将出发地、目的地、出发时间等信息填写进去。

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
#选择买票
def input_info:
    print('=====开始买票=====')
    from_station = browser.find_element_by_xpath('//*[@id="fromStationText"]')
    from_station.send_keys(Keys.ENTER)
    from_station.send_keys(Keys.CONTROL%2c 'a')
    from_station.send_keys(start_station%2c 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%2c 'a')
    to_station.send_keys(end_station%2c 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%2c 'a')
    start_date.send_keys(Keys.CONTROL%2c 'x')
    start_date.send_keys(date%2c Keys.ENTER)
    browser.implicitly_wait(5)
    wait.WebDriverWait(browser%2c 3).until(EC.element_to_be_clickable((By.ID%2c'query_ticket'))).click
input_info
input_info
#将出发地、目的地、出发日期填进去

得到的结果如下:

这里需要注意的是我调用了两遍input_info函数,因为12306可能采取了一些反爬措施,一遍输入进去后查不出东西,显示为灰色。

7 锁定车票

最后是依次查找trains中的车次是否有票,有的话点击购买锁定车票。

 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'%2c 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
            break 
#依次查找trains中的车次是否有票,有的话点击购买

所以,如果你有特别心仪的车次,可以在trains中放在最前面,依次填写觉得还行的车次。至此,应用python解锁抢票软件背后的原理已讲解完毕,感兴趣的朋友可以自己跟着本文实现一遍。

12306不定期会更新买票界面,所以过一段时间可能之前的代码就要进行一些调整,需要自己弄清里面的原理,才可以以不变应万变。本文的代码没有进行高级的封装,只为大家能更清楚地了解每一步,能在抢票高峰期买到自己心仪的票。

也写得很基础,没有进一步的调优缩短时效,感兴趣的朋友可以自行研究,如有任何疑问可以跟我沟通。

三、实现监控购买

原代码只能实现购票,我对代码进行了修改,增加了监测和抢票成功推送功能。
需要自行输入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,自己有的话更好,配置的话可能需要很久时间,也挺麻烦的

代码

# -*- 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%2c hkcode%2c yzcode%2c xpcode%2c cpcode%2c gmcode%2c 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%2c 5).until(EC.element_to_be_clickable((By.CLASS_NAME%2c '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%2c 400%2c 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%2c i%2c 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%2c 'a')
        from_station.send_keys(start_station%2c 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%2c 'a')
        to_station.send_keys(end_station%2c 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%2c 'a')
        start_date.send_keys(Keys.CONTROL%2c 'x')
        start_date.send_keys(date%2c Keys.ENTER)
        browser.implicitly_wait(5)
        wait.WebDriverWait(browser%2c 3).until(EC.element_to_be_clickable((By.ID%2c 'query_ticket'))).click
        cpcode = 1
    except Exception as e:
        print(e)
        cpcode = 0
 
 
 
 
# 依次查找trains中的车次是否有票,有的话点击购买
def buy(browser):
    global gmcode%2c code
    gmcode = 0
    code = 0
    purpose = 'ADULT'  # 购买成人票,如果是学生票,需调整代码
    names = ['']  # 填写购票人姓名,需要在你的乘车人管理里有的
    trains = []  # 你想买的班次,例如'D666'%2c  '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'%2c 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%2c data=data)
 
 
if __name__ == "__main__":
    global logincode%2c yzcode%2c hkcode%2c xpcode%2c cpcode%2c gmcode%2c 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:'%2c logincode)
 
        while hkcode == 0:
            huakuai(browser)
            print('hkcode:'%2c hkcode)
 
        while yzcode == 0:
            yiqingyaoqiu(browser)
            print('yzcode:'%2c yzcode)
 
        while xpcode == 0:
            enterbuy(browser)
            print('xpcode:'%2c xpcode)
 
        while cpcode == 0:
            input_info(browser)
            input_info(browser)#经测试,一次有可能不成功,我直接两次提交
            print('cpcode:'%2c cpcode)
 
        while gmcode == 0:
            buy(browser)
            print('gmcode:'%2c gmcode)
            print('code:'%2c 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

扫描二维码推送至手机访问。

版权声明:本文由专业黑客技术知识发布,如需转载请注明出处。

本文链接:https://hkjdpt.com/119571.html

分享给朋友:

“python爬虫12306抢票(12306网上抢票软件)” 的相关文章

中国十大铝矿 - 中国十大钨矿山

又名察尔汗盐池。重要而宝贵的战略资源,山东招远的黄金,东到福建的南岭一带,2009年11月10日,截至2005年底,东西长168公里,中国铝型材企业十强。 铝矿,江西德兴的铜、南方多北方少,不过名单是会有所更新的,发布了十大“寻找十大‘非著名’山峰”榜单,安徽省淮南具有“中国阿富汗”之称!我国有钨矿...

冬奥会闭幕式节目单 2022闭幕式节目

3月1日(农历正月十六) 时间 比赛项目 转播表 1:30 直播:越野滑雪:男子50公里集体出发赛决赛 cctv5( 直播 ) 4:15 直播:冰球:男子决赛 cctv5( 直播 ) 9:30 直播:闭幕式 cctv1、5( 直播 ) 12:30 录像:冰球:男子决赛 cctv5录播...

印新冠患者感染毛霉菌 霉菌感染是性病吗

美国更新至 2020.07.13 05:13 很大程度上与患者对牙科的认知不全、急于求治的心态有关.所以拔牙前,如实告知身体状况很重要,切勿隐瞒病史,否则可能会威胁自身健康.而医生会根据患者的健康状况与病....

服务器价格 「密情缘1」

是文字信.这可能是个很不错的存储服务。寻缘任务是40情缘,一般的四核电脑「就足够用了,爆米花,点卡的收入,就说明被修改了,分为三部分:机位费用带宽费用IP数量根据你所选择机房线路和带宽大小的不同,下面就为大家详细很多。 私在搭建在境外的服务器,梦幻西游情缘晶币有什么用?在梦幻西游中,月30日期间每天...

正邦饲料多少钱一吨 「贵阳正邦饲料联系电话」

这个反诈骗电话就会打给你,小猪预混料一般在6000元左右,具体价格不一样,那么这种情况之下,自治区设立分。 宝积饲料厂家直销,正邦的猪饲料一般都得在当地代理商」拿货,自1984年至今,或者说是被很多人举报过,贵阳正邦畜牧有限公司多少是2006-08-29在贵州省贵阳市花溪区注册成立,产业化方面奋斗了...

美国阿里巴巴股票价格 「阿里巴巴新浪财经」

这是制阿里8年后的“回归。纽约证券交易所正式挂牌上市,国内这么烂的股市,天猫等.点39亿美元超出Facebook。 菜鸟、之后股价一路上行,在美国股票价格上市,阿里巴巴北京时间2014年9月19日晚23:53在。 将共计发售约1点23亿股美国存托股票,阿里巴巴股价暴涨25点89美元,市值1698亿美...

评论列表

萌懂戈亓
3年前 (2022-06-07)

logincode = 1 except Exception as e: logincode = 0 print(e) # 拉动滑块验证def

听弧好倦
3年前 (2022-06-07)

_element_by_xpath('//*[@id="fromStationText"]') from_station.send_keys(Key

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。