Unconsciously, the annual Spring Festival ticket grabbing screen has been pulled open, want to grab the ticket home quickly?As a programmer, you must know about these techniques.
In order to make it faster and more convenient for people to grab train tickets, a variety of software for grabbing tickets should be created, most of which are mechanisms for paying for grabbing tickets.
As a programmer, how can I get a ticket home technically?Take a look at the ticket grabbing script written in Python.
Teach you how to grab a ticket with Python to go home for the New Year
Environmental introduction
windows 8.1
python3.6.1
firefox plugin geckodriver.exe
Operation steps
Introduce the required modules
from selenium import webdriver #Control Browser from selenium.webdriver.common.keys import Keys #Used to assign values to elements import time #Time Module from selenium.webdriver.support.select import Select #Control Dropdown Box Module from selenium.webdriver.common.by import By #Find Element Modules from selenium.webdriver.support.ui import WebDriverWait #"Show Waiting Module from selenium.webdriver.support import expected_conditions as EC #Waiting Conditions Module
Login Module
First, you need to choose the browser you want to use. Take firefox for example, download geckodriver.exe.
The stations.txt mentioned can look directly at this:
Station information:
https://kyfw.12306.cn/otn/resources/js/framework/station_name.js?station_version=1.9042
Put geckodriver.exe in the same directory as python.exe (if there are errors, put a file in the same directory as firefox.exe and add environment variables)
#Can be used input,You can also put it directly in the user name, password input box at the back #You can use standard input for batch operations. Here is an example of a personal ticket-grabbing operation # username = str(input('Please enter your user name:')) # password = str(input('Please enter your password:')) #These two lines can be ignored for now browser = webdriver.Firefox() #drive firefox Browser browser.get("https://kyfw.12306.cn/otn/login/init") #Enter the link after launching the browser browser.find_element_by_id('username').clear() browser.find_element_by_id('username').send_keys('xxxxx') #xxxxx Change to User Name browser.find_element_by_id('password').send_keys('xxxxx') #xxxxx Change to Password time.sleep(10) #At this point, the verification code clicks on itself, set a 10-second delay here, you can set your own try: browser.find_element_by_id('loginSub').click() #Click on the login action, the id For the login button #perhaps browser.find_element_by_link_text('Land').click() #Name of label display except: browser.find_element_by_class_name('touclick-bgimg touclick-reload touclick-reload-normal').click() #try Wrong Authentication Code Entry Point refreshes here time.sleep(20) #Wait 20 seconds before entering the verification code for the second time, you can set it yourself, and skip the first time without error browser.find_element_by_id('loginSub').click() #Click Login after Re-entering Authentication Code
Jump Module
#python Learning Group 592539176 #Jump to Home Page by Default time.sleep(2) #There is generally no need to set a time wait here, which is used when debugging code clickReserve = browser.find_element_by_link_text('Ticket Reservation').click() #Jump to the ticket booking page, which can query tickets time.sleep(2) #Departure and Arrival Settings #here value Value is the place of departure, BJP Represent Beijing, change value Values are not loaded on the page, take little time, and do not see the origin and destination from the page #Content here to crawl, saved in stations.txt In, each line represents an address and opens the document ctrl + F Find it jsf = 'var a = document.getElementById("fromStation");a.value = "BJP"' #Here you will BJP Change to the starting address you need, value Value is crawling to stations.txt Medium, view by yourself browser.execute_script(jsf) jst = 'var a = document.getElementById("toStation");a.value = "LZJ"' #Endpoint, same as above method browser.execute_script(jst) js = "document.getElementById('train_date').removeAttribute('readonly')" #Default time selection is read-only, via JS Remove read-only properties browser.execute_script(js) #implement JS Sentence browser.find_element_by_id('train_date').clear() #Time element has prompt by default, need to be cleared first browser.find_element_by_id('train_date').send_keys('2018-02-01') #Enter the time required to query according to the format change search = browser.find_element_by_id('query_ticket').click() #When you have entered the information, click on the query. There are adult tickets and student tickets. The default is adult tickets. If you buy, execute the following statement at the student ticket office: #browser.find_element_by_id('xxxx').click() #For id or class or other self-selection, [see here] (http://blog.51cto.com/12376665/2052278)
Start buying tickets
Here, click on a scheduled action, and I'm just going to give you an example of how you can do this, or you can click on it until you succeed (which avoids the impact of the site countdown and the time lag between actual time, but you don't know if 12306 has any restrictions on fast and continuous access when you are snapping tickets).
start_time = "Thu Jan 04 08:00:00 2018" #Set the time to grab tickets first b = time.mktime(time.strptime(start_time,"%a %b %d %H:%M:%S %Y")) print(time.strftime("%a %b %d %H:%M:%S %Y", time.localtime(b)) ) #This is for debugging code usage and is ignored without affecting usage a = float(b)-time.time() #Subtract the timestamp of the current time from the time you set time.sleep(a) #The number of seconds from the previous step is the time to wait for a ticket to be grabbed try: #There were originally try That's enough. WebDriverWait There is already a corresponding waiting duplicate access mechanism, defaulting to 0.5 Try once a second, except Add in just in case WebDriverWait(browser,10).until(EC.presence_of_element_located((By.ID, "ticket_2400000Z550L"))) #Find the one that needs a reservation id,Until it appears, 10 means wait for 10 seconds ticket = browser.find_element_by_xpath('//tr[@id="ticket_2400000Z550L"]/td[13]/a').click() #Click the Reserve button except: browser.find_element_by_id('query_ticket').click() WebDriverWait(browser, 10).until(EC.presence_of_element_located((By.ID, "ticket_2400000Z550L"))) ticket = browser.find_element_by_xpath('//tr[@id="ticket_2400000Z550L"]/td[13]/a').click() """ normalPassenger_8 Number indicates the number under the account, default from 0 if the first is normalPassenger_0 """WebDriverWait(browser,10).until(EC.presence_of_element_located((By.ID, "normalPassenger_8"))) browser.find_element_by_id('normalPassenger_8').click() #id 8 in the account represents the ninth place under the account s = Select(browser.find_element_by_id('seatType_1')) s.select_by_value('6') #here value Look at the following categories, 6 for advanced soft sleepers browser.find_element_by_id('submitOrder_id').click() WebDriverWait(browser,10).until(EC.presence_of_element_located((By.ID, "qr_submit_id"))) browser.find_element_by_link_text('place order') browser.find_element_by_id('qr_submit_id').click()#-------------------------------------------------End#Hard seat 1#Hard sleeping 3#Soft sleeping 4#Advanced soft sleeping 6#Second-class seat O(Capital letters)#First class seats M#Business 9
summary
Where to replace:
-
User name, password.
-
value values for start and destination can be modified by checking stations.txt.
-
Departure time.
-
Select the xpath path path of the train number by yourself. The path does not need to change, just change the corresponding id.
-
Check the location of the user (default: normalPassenger_0 if only one user is required).
-
The seat category selected defaults to the cheapest of the categories with tickets.
The rest of the tests are the same, no changes were found. Before using, you can test the code. The test is to note that the code submitting the order is commented out (the order is unrestricted, it seems you can only cancel three times a day), and the network speed is normal during the test.
Some people say that browser execution is slower. It's true that scripts that can directly identify the authenticator code will be faster without an interface, but it actually takes as long as it is scheduled to start and end. On the same network, code execution is faster than manual operation.
In addition, time can be studied. Previously, the time of a treasure was studied. The time of second killing was a few seconds ahead of Beijing time, and there was a small time difference across the country.
Complete script example
#python Learning Group 592539176 #python3.6.1#data: 2018-01-03#author:LGC247CG""" Explain: 1.The script mainly provides a way of implementation, there are many ways to achieve, there are many places to optimize, trigger mechanism can also be set by itself, the code is compressed to the minimum, just for everyone to understand 2.Under normal network conditions, when the specified time is not set, the time from clicking on the confirmation code to placing the order is almost one second, so it is still OK in speed 3.Since it takes almost the same time to select multiple users and single users at the same time, we hope that this method can only be used for technical communication, not as a cattle. 4.In the case of technical exchange, if the verification code can be implemented, automatic ticket grabbing can be fully realized: --1>Verification codes have a certain regularity and number, you can use scripts to get all pictures and label them accordingly --2>Match the text and labels of the page, calculate the similarity of the pictures, and click on the corresponding pictures --3>Or a picture recognition model that trains in-depth learning and is identified by an algorithm """from selenium import webdriverfrom selenium.webdriver.common.keys import Keysimport timefrom selenium.webdriver.support.select import Selectfrom selenium.webdriver.common.by import Byfrom selenium.webdriver.support.ui import WebDriverWaitfrom selenium.webdriver.support import expected_conditions as EC browser = webdriver.Firefox() browser.get("https://kyfw.12306.cn/otn/login/init") browser.find_element_by_id('username').clear() browser.find_element_by_id('username').send_keys('xxxxxxx') browser.find_element_by_id('password').send_keys('xxxxxxx') time.sleep(10)try: browser.find_element_by_id('loginSub').click()except: browser.find_element_by_class_name('touclick-bgimg touclick-reload touclick-reload-normal').click() time.sleep(15) browser.find_element_by_id('loginSub').click()#Jump to ticket booking page time.sleep(2) clickReserve = browser.find_element_by_link_text('Ticket Reservation').click()#Set WebDriverWait (browser, 10). until (EC.presence_of_element_located((By.ID,'fromStation')) for departure and arrival locations jsf = 'var a = document.getElementById("fromStation");a.value = "BJP"'browser.execute_script(jsf) jst = 'var a = document.getElementById("toStation");a.value = "LZJ"'browser.execute_script(jst) js = "document.getElementById('train_date').removeAttribute('readonly')"browser.execute_script(js) browser.find_element_by_id('train_date').clear() browser.find_element_by_id('train_date').send_keys('2018-02-02') search = browser.find_element_by_id('query_ticket').click()#For time, I always feel that the time calculated by the website is about a second different from the time I get, this is tested by myself in different environments start_time = "Thu Jan 04 10:00:00 2018" #First set the time B = time.mktime (time.strptime (start_time, "%a%b%d%H:%M:%S%Y") print(time.strftime("%a %b %d %H:%M:%S %Y", time.localtime(b)) ) #This is for debugging code usage and is ignored without affecting usage a = float(b)-time.time() #Subtract the timestamp of the current time from the time you set time.sleep(a) #The number of seconds from the previous step is the time to wait for a ticket to be grabbed browser.find_element_by_id('query_ticket').click() #It's time to click on the query to refresh in case the element try is not found: WebDriverWait(browser,10).until(EC.presence_of_element_located((By.ID, "ticket_2400000Z550L"))) ticket = browser.find_element_by_xpath('//tr[@id="ticket_2400000Z550L"]/td[13]/a').click()except: browser.find_element_by_id('query_ticket').click() WebDriverWait(browser, 10).until(EC.presence_of_element_located((By.ID, "ticket_250000K8880L"))) ticket = browser.find_element_by_xpath('//tr[@id="ticket_250000K8880L"]/td[13]/a').click()""" normalPassenger_8 Number indicates the number under the account, default from 0 if the first is normalPassenger_0 """WebDriverWait(browser,10).until(EC.presence_of_element_located((By.ID, "normalPassenger_8"))) browser.find_element_by_id('normalPassenger_8').click() s = Select(browser.find_element_by_id('seatType_1')) s.select_by_value('6') browser.find_element_by_id('submitOrder_id').click() WebDriverWait(browser,10).until(EC.presence_of_element_located((By.ID, "qr_submit_id"))) browser.find_element_by_link_text('place order')#browser.find_element_by_id('qr_submit_id').click()