Teach you how to realize 12306 automatic ticket grabbing in Python 3. Beginners must learn

Recently, I was learning python, so I wrote this 12306 ticket grabbing script in Python, shared it with you, and shared it with you. If there is something wrong, please correct it. Don't say much, go to the main topic: before going to the main topic, I want to explain that due to the update of 12306 official website, the script has made a little change. The specific modified source code can be viewed on GitHub New script source


Also note: whether you are for Python employment or hobbies, remember: project development experience is always the core. If you don't have the latest Python introduction to advanced practical video tutorial in 2020, you can go to the small Python exchange : you can find a lot of new Python tutorial projects under the transformation of "seven clothes, nine seven buses and five numbers" (homophony of numbers). You can also exchange and consult with the old drivers!

At present, this script can only be used for one trip. The number of people can be multiple. It supports selecting as type, etc.
The implementation idea is to simulate the browser login and operation by splinter.browser. As the 12306 verification code is not easy to identify automatically, the verification code needs to be manually identified by the user, and the login operation is carried out. After that, the script can operate. Here are some screenshots of my test:

Step 1: as shown in the figure below, first enter the basic information of ticket grabbing

Step 2: then enter the login page. You need to enter the verification code manually and click login

Step 3: after landing, automatically enter the ticket grabbing page, as shown in the following figure

Finally: just wait for the result of ticket swiping. As shown in the figure below, it means that the ticket swiping is successful. After the ticket is swiped, there will be SMS and email notification. Please remember to go to 12306 in time for payment, or it will be robbed in vain.

Python running environment: Python 3.6
Modules used: re, splinter, time, sys, httplib2, urlib, smtplib, email
For the modules not installed, please use PIP installll to install, for example: PIP install splitter
The following code is the introduction of all modules used in 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 code

 

Information preparation before ticket swiping: I'll mainly talk about obtaining the cookie value of the origin and destination. When entering the city, you need to use the cookie value. The cookie value can be found on the 12306 official website. Then you can see it in the query request cookie in the network of F12 (I believe all coder s know this). You can find it in the header of the request. The value of [JC] save [fromstation] is For the cookie of the departure station, the value of  JC  save  tostation is the cookie of the destination, and then it can be added to the cookie dictionary city  list of the city in the code. The key is the initial of the city, and the value is the form of the cookie value.

For ticket grabbing, you must log in first. The simulated Login operation here will automatically fill in the account name and password of 12306. Of course, you can also modify the account and password in the open browser. The key codes are as follows:

 

 

 

def do_login(self):
    """The login function is realized, and the manual identification verification code is used 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:
        if self.driver.url != self.init_my_url:
            sleep(1)
        else:
            break
Copy code

 

After logging in, it is to control all kinds of operation processing of ticket swiping. Here, I will not paste the code, because there are many codes. Don't worry. In the end, I will paste the complete code.

When the ticket is swiped successfully, I will give a double notice of SMS and email. Of course, the platform of SMS notice here depends on which specific code you use to modify. What I use is Mutual wireless The free SMS notification interface of the experience version of. I use the smtplib for the email sending module and the 163 mailbox for the email server. If you use the 163 mailbox, you haven't set the client authorization password yet. Remember to set the client authorization password first, which is very convenient. The following is the main implementation code:

 

 

 

def send_sms(self, mobile, sms_info):
    """Send a mobile notification message with-Mutual wireless-Test SMS for"""
    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"""
    # Connection mailbox server information
    host = 'smtp.163.com'
    port = 25
    sender = 'xxxxxx@163.com'  # Your email number
    pwd = '******'  # It's not a login password, it's a client authorization password
    # Sending information
    receiver = receiver_address
    body = '<h2>Warm reminder:</h2><p>' + content + '</p>'
    msg = MIMEText(body, 'html', _charset="utf-8")
    msg['subject'] = 'Ticket snatching success notice!'
    msg['from'] = sender
    msg['to'] = receiver
    s = smtplib.SMTP(host, port)
    # Start to log in email and send email
    s.login(sender, pwd)
    s.sendmail(sender, receiver, msg.as_string())
Copy code

 

I've said so much. I feel like I've said a lot of rubbish. Haha, I'm sorry to delay your time to see me. I've pasted the source code that you are most concerned about. Please take the code. If you have any problems during the trial operation, you can leave me a message or send me a private message. I see that you will reply in time:

 

 

 

#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
//Swipe 12306 train ticket through splinter
//The account password can be filled in automatically. At the same time, the account password can be modified during login
//Then manually identify the verification code and log in. The next thing is left to the script to do. Just wait for the result of ticket grabbing (the browser cannot be closed during the ticket swiping process)
author: 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 buying and its implementation"""

    def __init__(self, user_name, password, passengers, from_time, from_station, to_station, number, seat_type, receiver_mobile, receiver_email):
        """Defining instance properties, initializing"""
        # 1206 account password
        self.user_name = user_name
        self.password = password
        # Passenger name
        self.passengers = passengers
        # Starting station and terminal station
        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':
            seat_type_index = 2
            seat_type_value = 'M'
        elif seat_type == 'second-class seat':
            seat_type_index = 3
            seat_type_value = 0
        elif seat_type == 'high-grade soft berth':
            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 position':
            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 seats':
            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 information
        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/chromeddriver/downloads
        self.driver_name = 'chrome'
        self.executable_path = 'C:\\Users\cuizy\AppData\Local\Programs\Python\Python36\Scripts\chromedriver.exe'

    def do_login(self):
        """The login function is realized, and the manual identification verification code is used 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:
            if self.driver.url != self.init_my_url:
                sleep(1)
            else:
                break

    def start_brush(self):
        """Realization of ticket buying function"""
        self.driver = Browser(driver_name=self.driver_name, executable_path=self.executable_path)
        # Size of browser window
        self.driver.driver.set_window_size(900, 700)
        self.do_login()
        self.driver.visit(self.ticket_url)
        try:
            print('Start swiping tickets')
            # Loading 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 first%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 == '--':
                        print('There is no such seat type for sale. The current ticket swiping has ended. Please reopen!')
                        sys.exit(1)
                    elif current_tr.find_by_tag('td')[self.seat_type_index].text == 'nothing':
                        print('No tickets, keep trying')
                    else:
                        # Tickets available, try to book
                        print('The tickets have been swiped' + str(current_tr.find_by_tag('td')[self.seat_type_index].text) + '),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 users
                            print('Start selecting users')
                            self.driver.find_by_text(p).last.click()
                            # Select seat type
                            print('Begin to choose a farewell')
                            if self.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('Submitting order')
                        self.driver.find_by_id('submitOrder_id').click()
                        sleep(2)
                        # Check whether the playback result is normal
                        submit_false_info = self.driver.find_by_id('orderResultInfo_id')[0].text
                        if submit_false_info != '':
                            print(submit_false_info)
                            self.driver.find_by_id('qr_closeTranforDialog_id').click()
                            sleep(0.2)
                            self.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 information
                        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 don't disclose the verification 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 mobile notification message with-Mutual wireless-Test SMS for"""
        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"""
        # Connection mailbox server information
        host = 'smtp.163.com'
        port = 25
        sender = '******@163.com'  # Your email number
        pwd = '******'  # It's not a login password, it's a client authorization password
        # Sending information
        receiver = receiver_address
        body = '<h2>Warm reminder:</h2><p>' + content + '</p>'
        msg = MIMEText(body, 'html', _charset="utf-8")
        msg['subject'] = 'Ticket snatching success notice!'
        msg['from'] = sender
        msg['to'] = receiver
        s = smtplib.SMTP(host, port)
        # Start to log in email and send email
        s.login(sender, pwd)
        s.sendmail(sender, receiver, msg.as_string())


if __name__ == '__main__':
    # 12306 user name
    user_name = input('Please enter 12306 user name:')
    while user_name == '':
        user_name = input('12306 The user name cannot be empty. Please re-enter:')
    # 12306 login password
    password = input('Please enter 12306 login password:')
    while password == '':
        password = input('12306 The login password cannot be blank. Please re-enter:')
    # Passenger name
    passengers_input = input('Please enter the passenger's name, multiple people use English comma“,"Connection (e.g. single "Zhang San" or multiple "Zhang San,Li Si "):')
    passengers = passengers_input.split(",")
    while passengers_input == '' or len(passengers) > 4:
        print('At least 1 passenger and at most 4 passengers!')
        passengers_input = input('Please re-enter the passenger's name, multiple people use English comma“,"Connection (e.g. single "Zhang San" or multiple "Zhang San,Li Si "):')
        passengers = passengers_input.split(",")
    # Travel date
    from_time = input('Please enter the travel date (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('The boarding date cannot be empty or the 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',  # Taiyuan
        'yc': '%u8FD0%u57CE%2CYNV',  # Yuncheng
        'gzn': '%u5E7F%u5DDE%u5357%2CIZQ',  # Guangzhou South
        'wzn': '%u68A7%u5DDE%u5357%2CWBZ',  # Wuzhou South
    }
    # Departure station
    from_input = input('Please input the departure station, just input the initial (for example, Beijing“ bj"): ')
    while from_input not in city_list.keys():
        from_input = input('The departure station cannot be empty or does not support the current departure station (please contact the administrator if necessary!) , please re-enter:')
    from_station = city_list[from_input]
    # Terminus
    to_input = input('Please input the terminal, just input the initial (for example, Beijing“ bj"): ')
    while to_input not in city_list.keys():
        to_input = input('The terminal cannot be empty or does not support the current terminal (please contact the administrator if necessary!) , please re-enter:')
    to_station = city_list[to_input]
    # Train number
    number = input('Please enter the train number (for example“ G110"): ')
    while number == '':
        number = input('Train number cannot be empty, please re-enter:')
    # Seat type
    seat_type = input('Please enter the seat type (e.g. "soft sleeper"):')
    

Tags: Python Mobile pip PHP

Posted on Thu, 07 May 2020 19:52:11 -0700 by pabs1983