Recently, I am learning Python, so I wrote this script with Python to grab tickets for 12306, and share it with you. If there is something wrong, please correct it. Without further ado, to the point:
Before entering the topic, I would like to clarify that, due to the revision of 12306.cn, so the script has made a small change, the specific modified source code, you can go to GitHub above view… New script source
This script can only brush a car, the number of people can be multiple, support selection as a type, etc. The implementation idea is splinter. Browser simulates browser login and operation, because 12306 verification code is not automatic recognition, so, the verification code needs to be manually recognized by users, and login operation, after the matter, it can be handed over to the script operation, the following is some screenshots of my test time:
Step 1: Enter the basic information of ticket snatching as shown below
Step 2: Then enter the login page, need to manually enter the verification code, and click login operation
Step 3: After login, the page of ticket snatching will be automatically entered, as shown in the picture below
Finally: is to wait for the result of brushing tickets, as shown in the following picture, it is said that brushing tickets successfully, brushing tickets, will be SMS and email notification, please remember to pay in time to 12306, otherwise it will be robbed in vain.
Python operating environment: Python3.6 Modules used: re, splinter, time, sys, Httplib2, urllib, smtplib, email PIP install splinter The following code is the introduction of all modules used by this script:
import re
from splinter.browser import Browser
from time import sleep
import sys
import httplib2
from urllib import parse
import smtplib
from email.mime.text import MIMEText
Copy the code
To prepare the information before brushing, I mainly talk about the cookie value of the originating station and destination, because the city needs to be entered through the cookie value, and the cookie value can be accessed through 12306.cn. In the header of the request, the _jc_save_fromStation value is the cookie of the starting station. The value of _jc_save_toStation is the cookie of the destination, and then added to the cookie dictionary city_list of the city in the code. The key is the first letter of the city, and the value is in the form of the cookie value.
The login operation I simulate here will automatically fill in the account name and password of 12306. Of course, you can also change the account name and password in the open browser. The key codes are as follows:
def do_login(self):
"""Login function realization, manual identification verification code for login"""
self.driver.visit(self.login_url)
sleep(1)
self.driver.fill('loginUserDTO.user_name', self.user_name)
self.driver.fill('userDTO.password', self.password)
print('Please enter the verification code... ')
while True:
ifself.driver.url ! = self.init_my_url: sleep(1)else:
break
Copy the code
After login, is to control the various operations of the brush ticket processing, here, I will not paste the code, because the code is more, do not worry, in the end, I will post a complete code.
When the ticket is swiping successfully, I will make the double notification of SMS and email. Of course, the platform of SMS notification depends on which code you modify. I use the free SMS notification interface of the experience version of Huyi Wireless. I use SMtPLib to send mail module, and 163 mailbox to send mail server. If 163 mailbox is used, you have not set the client authorization password, remember to set the client authorization password first, it is very convenient. Here is the main implementation code:
def send_sms(self, mobile, sms_info):
"""Send a cell phone notification text message, using a test text message. - Wax wireless."""
host = "106.ihuyi.com"
sms_send_uri = "/webservice/sms.php? method=Submit"
account = "C59782899"
pass_word = "19d4d9c0796532c7328e8b82e2812655"
params = parse.urlencode(
{'account': account, 'password': pass_word, 'content': sms_info, 'mobile': mobile, 'format': 'json'}
)
headers = {"Content-type": "application/x-www-form-urlencoded"."Accept": "text/plain"}
conn = httplib2.HTTPConnectionWithTimeout(host, port=80, timeout=30)
conn.request("POST", sms_send_uri, params, headers)
response = conn.getresponse()
response_str = response.read()
conn.close()
return response_str
def send_mail(self, receiver_address, content):
"""Send email notification"""
Connect to email server information
host = 'smtp.163.com'
port = 25
sender = '[email protected]' # Your sender email number
pwd = '* * * * * *' # not login password, is the client authorization password
# Send a message
receiver = receiver_address
body = ' Reminder:
'
+ content + '</p>'
msg = MIMEText(body, 'html', _charset="utf-8")
msg['subject'] = 'Notice of success! '
msg['from'] = sender
msg['to'] = receiver
s = smtplib.SMTP(host, port)
Start logging in to the mailbox and sending the email
s.login(sender, pwd)
s.sendmail(sender, receiver, msg.as_string())
Copy the code
Said so much, feeling is said a lot of nonsense ah, ha ha, sorry, delay your time to see me nonsense, I post everyone most concerned about the source code, please pick up the code, everyone in the process of trying to run, there is any problem, you can give me a message or private letter I, I see will be timely reply to you:
#! /usr/bin/env python
# -*- coding: utf-8 -*-
"""You can use Splinter to swipe the 12306 train ticket to automatically fill in your account password. At the same time, you can also change your account password, manually identify the verification code, and log in. The rest of the work is done by the script. cuizy time: 2018-05-30 """
import re
from splinter.browser import Browser
from time import sleep
import sys
import httplib2
from urllib import parse
import smtplib
from email.mime.text import MIMEText
class BrushTicket(object):
"""Ticket categories and implementation methods"""
def __init__(self, user_name, password, passengers, from_time, from_station, to_station, number, seat_type, receiver_mobile, receiver_email):
"""Define instance properties, initialize"""
# 1206 Password of account
self.user_name = user_name
self.password = password
# Passenger name
self.passengers = passengers
# Starting and ending stations
self.from_station = from_station
self.to_station = to_station
# Travel date
self.from_time = from_time
# Train number
self.number = number.capitalize()
Td position of seat type
if seat_type == 'Business Class':
seat_type_index = 1
seat_type_value = 9
elif seat_type == 'First class':
seat_type_index = 2
seat_type_value = 'M'
elif seat_type == 'Second class':
seat_type_index = 3
seat_type_value = 0
elif seat_type == 'Superior Soft sleeper':
seat_type_index = 4
seat_type_value = 6
elif seat_type == 'soft sleeper':
seat_type_index = 5
seat_type_value = 4
elif seat_type == 'moving lie':
seat_type_index = 6
seat_type_value = 'F'
elif seat_type == 'hard sleeper':
seat_type_index = 7
seat_type_value = 3
elif seat_type == 'soft seat':
seat_type_index = 8
seat_type_value = 2
elif seat_type == 'hard seat':
seat_type_index = 9
seat_type_value = 1
elif seat_type == 'no seat':
seat_type_index = 10
seat_type_value = 1
elif seat_type == 'other':
seat_type_index = 11
seat_type_value = 1
else:
seat_type_index = 7
seat_type_value = 3
self.seat_type_index = seat_type_index
self.seat_type_value = seat_type_value
# Notification message
self.receiver_mobile = receiver_mobile
self.receiver_email = receiver_email
# Main page URL
self.login_url = 'https://kyfw.12306.cn/otn/login/init'
self.init_my_url = 'https://kyfw.12306.cn/otn/index/initMy12306'
self.ticket_url = 'https://kyfw.12306.cn/otn/leftTicket/init'
# browser driver information, driver download page: https://sites.google.com/a/chromium.org/chromedriver/downloads
self.driver_name = 'chrome'
self.executable_path = 'C:\\Users\cuizy\AppData\Local\Programs\Python\Python36\Scripts\chromedriver.exe'
def do_login(self):
"""Login function realization, manual identification verification code for login"""
self.driver.visit(self.login_url)
sleep(1)
self.driver.fill('loginUserDTO.user_name', self.user_name)
self.driver.fill('userDTO.password', self.password)
print('Please enter the verification code... ')
while True:
ifself.driver.url ! = self.init_my_url: sleep(1)else:
break
def start_brush(self):
"""Purchase ticket function realization"""
self.driver = Browser(driver_name=self.driver_name, executable_path=self.executable_path)
The size of the browser window
self.driver.driver.set_window_size(900, 700)
self.do_login()
self.driver.visit(self.ticket_url)
try:
print('Start counting tickets... ')
# Load ticket query information
self.driver.cookies.add({"_jc_save_fromStation": self.from_station})
self.driver.cookies.add({"_jc_save_toStation": self.to_station})
self.driver.cookies.add({"_jc_save_fromDate": self.from_time})
self.driver.reload()
count = 0
while self.driver.url.split('? ')[0] == self.ticket_url:
self.driver.find_by_text('query').click()
sleep(1)
count += 1
print('The %d click to query... ' % count)
try:
car_no_location = self.driver.find_by_id("queryLeftTable")[0].find_by_text(self.number)[1]
current_tr = car_no_location.find_by_xpath(". /.. /.. /.. /.. /..")
if current_tr.find_by_tag('td')[self.seat_type_index].text == The '-':
print('No seat type for sale, current brushing has ended, please reopen! ')
sys.exit(1)
elif current_tr.find_by_tag('td')[self.seat_type_index].text == 'no':
print('No tickets, keep trying... ')
else:
# Tickets available, try to book
print('Tickets are counted (remaining votes:' + str(current_tr.find_by_tag('td')[self.seat_type_index].text) + ') and start trying to book... ')
current_tr.find_by_css('td.no-br>a')[0].click()
sleep(1)
key_value = 1
for p in self.passengers:
# Select user
print('Start selecting users... ')
self.driver.find_by_text(p).last.click()
# Select seat type
print('Start choosing seats... ')
ifself.seat_type_value ! = 0: seat_select = self.driver.find_by_id("seatType_" + str(key_value))[0]
seat_select.find_by_xpath("//option[@value='" + str(self.seat_type_value) + "']")[0].click()
key_value += 1
sleep(0.5)
if p[-1] == ') ':
self.driver.find_by_id('dialog_xsertcj_ok').click()
print('Placing orders... ')
self.driver.find_by_id('submitOrder_id').click()
sleep(2)
# check whether the result is normal
submit_false_info = self.driver.find_by_id('orderResultInfo_id')[0].text
ifsubmit_false_info ! =' ':
print(submit_false_info)
self.driver.find_by_id('qr_closeTranforDialog_id'Self). Click () sleep (0.2). The driver. Find_by_id ('preStep_id'). Click () sleep (0.3)continue
print('Confirming order... ')
self.driver.find_by_id('qr_submit_id').click()
print(Reservation successful, please pay in time...... ')
Send notification messages
self.send_mail(self.receiver_email, 'Congratulations, you have got the ticket, please go to 12306 to pay the order in time! ')
self.send_sms(self.receiver_mobile, 'Your verification code is 8888. Please do not divulge the captcha code to others. ')
except Exception as error_info:
print(error_info)
except Exception as error_info:
print(error_info)
def send_sms(self, mobile, sms_info):
"""Send a cell phone notification text message, using a test text message. - Wax wireless."""
host = "106.ihuyi.com"
sms_send_uri = "/webservice/sms.php? method=Submit"
account = "C59782899"
pass_word = "19d4d9c0796532c7328e8b82e2812655"
params = parse.urlencode(
{'account': account, 'password': pass_word, 'content': sms_info, 'mobile': mobile, 'format': 'json'}
)
headers = {"Content-type": "application/x-www-form-urlencoded"."Accept": "text/plain"}
conn = httplib2.HTTPConnectionWithTimeout(host, port=80, timeout=30)
conn.request("POST", sms_send_uri, params, headers)
response = conn.getresponse()
response_str = response.read()
conn.close()
return response_str
def send_mail(self, receiver_address, content):
"""Send email notification"""
Connect to email server information
host = 'smtp.163.com'
port = 25
sender = '******@163.com' # Your sender email number
pwd = '* * * * * *' # not login password, is the client authorization password
# Send a message
receiver = receiver_address
body = ' Reminder:
'
+ content + '</p>'
msg = MIMEText(body, 'html', _charset="utf-8")
msg['subject'] = 'Notice of success! '
msg['from'] = sender
msg['to'] = receiver
s = smtplib.SMTP(host, port)
Start logging in to the mailbox and sending the email
s.login(sender, pwd)
s.sendmail(sender, receiver, msg.as_string())
if __name__ == '__main__':
# 12306 Username
user_name = input('Please enter 12306 username:')
while user_name == ' ':
user_name = input('12306 username cannot be empty, please re-enter: ')
# 12306 Login password
password = input('Please enter 12306 login password:')
while password == ' ':
password = input('12306 Login password cannot be empty, please re-enter: ')
# Passenger name
passengers_input = input('Please enter the name of the passenger, and use the English comma ", "to connect, (e.g., single" John "or multiple" John ") :')
passengers = passengers_input.split(",")
while passengers_input == ' ' or len(passengers) > 4:
print('At least one passenger, at most four! ')
passengers_input = input('Please re-enter the name of the passenger, and use the English comma ", "to connect multiple passengers (e.g., single" John "or multiple" John ") :')
passengers = passengers_input.split(",")
# Travel date
from_time = input('Please enter the date of travel (e.g. "2018-08-08") :')
date_pattern = re.compile(r'^\d{4}-\d{2}-\d{2}$')
while from_time == ' ' or re.findall(date_pattern, from_time) == []:
from_time = input('Ride date cannot be empty or time format is incorrect, please re-enter:')
# City Cookie Dictionary
city_list = {
'bj': '%u5317%u4EAC%2CBJP'.# Beijing
'hd': '%u5929%u6D25%2CTJP'.# handan
'nn': '%u5357%u5B81%2CNNZ'.# nanning
'wh': '%u6B66%u6C49%2CWHN'.# wuhan
'cs': '%u957F%u6C99%2CCSQ'.# changsha
'ty': '%u592A%u539F%2CTYV'.# in taiyuan
'yc': '%u8FD0%u57CE%2CYNV'.# yuncheng
'gzn': '%u5E7F%u5DDE%u5357%2CIZQ'.# south guangzhou
'wzn': '%u68A7%u5DDE%u5357%2CWBZ'.# wuzhou south
}
# start
from_input = input('Please enter the departure station, just enter the first letter (e.g. Beijing "BJ") :')
while from_input not in city_list.keys():
from_input = input('Departure station cannot be empty or unsupported (please contact your administrator if necessary!) , please re-enter: ')
from_station = city_list[from_input]
# the terminal
to_input = input('Please enter the destination, just enter the first letter (e.g. Beijing "BJ") :')
while to_input not in city_list.keys():
to_input = input('Terminal cannot be empty or not supported by current terminal (please contact administrator if necessary!) , please re-enter: ')
to_station = city_list[to_input]
# Train number
number = input('Please enter the train number (e.g.' G110 ') : ')
while number == ' ':
number = input('Train number cannot be empty, please re-enter:')
# Seat type
seat_type = input('Please enter seat type (e.g.' soft sleeper ') : ')
while seat_type == ' ':
seat_type = input('Seat type cannot be empty, please re-enter:')
# Grab tickets successfully, notify the mobile phone number
receiver_mobile = input('Please reserve a mobile phone number for notification (e.g. 18888888888) :')
mobile_pattern = re.compile(r'^1{1}\d{10}$')
while receiver_mobile == ' ' or re.findall(mobile_pattern, receiver_mobile) == []:
receiver_mobile = input('Reserved mobile phone number cannot be empty or incorrectly formatted, please re-enter:')
receiver_email = input('Please reserve an email address for notification (e.g. [email protected]) :')
while receiver_email == ' ':
receiver_email = input('Reserved mailbox cannot be empty, please re-enter:')
# Start grabbing tickets
ticket = BrushTicket(user_name, password, passengers, from_time, from_station, to_station, number, seat_type, receiver_mobile, receiver_email)
ticket.start_brush()
Copy the code