本帖最后由 沧浪之水濯我心 于 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
|