python+selenium+request实行全自动12306抢票和购票

这次我总算是没有鸽,花了几天做了个脚本
原理:
1,通过selenium做UI方面的点击等待事件
2,使用request来判断出登录时的验证码识别事件
功能:
由于时间太短了,所以做的比较简陋,主要是做了,
1,区分车次,GXXXX,DXXXX等
2,几等座(测试时已二等座为例,穷b只能买得起二等座了…这里提供了所有座位类型判定)
3,,选择联系人(这个很多脚本里没写,个人觉得这个蛮重要的,因为默认都是第一个,但是这里提供了可以选择其他位置的人)
4,出发日期,这个就不说了
用途:
1,买的上,直接到抢票成功,支付方式里
2,试着抢票,抢了100次,没出现异常情况,一般我们抢票也差不多了,多的没时间去测试…
话不多说,直接上代码
login_for_cookie.py
因为12306在多次登录时,会出现限制你再次登录
所以这里直接用一次登录获取cookie,然后在调试期间都是直接用cookie登录


from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait

from Code import Code
import time

class Login():

    def __init__(self, driver):
        self.driver = driver
        self.login_url = 'https://kyfw.12306.cn/otn/login/init'
        self.login_success_url = 'https://kyfw.12306.cn/otn/view/index.html'
        self.ticket_url = 'https://kyfw.12306.cn/otn/leftTicket/init'
        self.person_info_url = 'https://kyfw.12306.cn/otn/confirmPassenger/initDc'

    def get_login_info(self):
        with open('info.txt', 'r') as f:
            lines = f.readlines()
            username = lines[0].split()
            password = lines[1].split()
        f.close()
        return [username, password]

    def login_step(self):
        username = self.get_login_info()[0]
        password = self.get_login_info()[1]
        self.driver.get(self.login_url)  # 进入登录界面
        self.driver.maximize_window()  # 最大化
        u = self.driver.find_element_by_id('username')  # 用户名
        p = self.driver.find_element_by_id('password')  # 密码
        button = self.driver.find_element_by_id('loginSub')  # 登录
        u.clear()
        u.send_keys(username)  # 输入用户名
        p.clear()
        p.send_keys(password)  # 输入密码
        Code(self.driver).main()  # 调用识别验证码
        button.click()  # 点击登录界面
        time.sleep(2)
        cookie = self.driver.get_cookie('tk')
        print(cookie)
        with open('cookie.txt', 'w') as f:
            f.write(str(cookie))

    def login(self):
        self.login_step()  # 登录
        while True:
            if self.driver.current_url == self.login_success_url:
                print('----------->登录成功')
                self.driver.quit()
                break
            else:
                print('----------->正在等待跳转')
if __name__ == '__main__':
    login = Login(driver=webdriver.Chrome())
    login.login()

Code.py
此代码为解析登录时出现的识别认证码

import requests
from PIL import Image
from selenium.webdriver import ActionChains
import time
from io import BytesIO


class Code():
    def __init__(self, browser):
        self.browser = browser
        self.verify_url = 'http://littlebigluo.qicp.net:47720/'     #验证码识别网址,返回识别结果

        #确定验证码的位置
    def get_position(self):
        time.sleep(3)
        element = self.browser.find_element_by_class_name('touclick-image')
        time.sleep(2)
        location = element.location
        size = element.size
        position= (location['x'], location['y'], location['x'] + size['width'], location['y'] + size['height'])
        return position

        #截取整个网页页面
    def get_screenshot(self):
        screenshot = self.browser.get_screenshot_as_png()
        screenshot = Image.open(BytesIO(screenshot))
        return screenshot

        #从截取的网页,裁剪出验证码图片,并保存到本地
    def get_touclick_img(self, name = 'captcha.png'):
        position = self.get_position()
        print('验证码的位置:', position)
        screenshot = self.get_screenshot()
        captcha = screenshot.crop(position)
        captcha.save('captcha.png')

        #验证码解析
    def parse_img(self):
        pic_name = 'captcha.png'
        response=requests.request("POST", self.verify_url, files={'pic_xxfile': open(pic_name, 'rb')})
        time.sleep(5)
        num = response.text.split('')[1].split('')[0]
        print('验证码识别成功!图片位置:%s' % num)
        try:
            if int(num):
                return [int(num)]
        except ValueError:
            num = list(map(int,num.split()))
            return num

        #识别结果num都以列表形式返回,方便后续验证码的点击

        #实现验证码自动点击
    def move(self):
        num = self.parse_img()
        try:
            element = self.browser.find_element_by_class_name('touclick-img-par')
            for i in num:
                if i <= 4:
                    ActionChains(self.browser).move_to_element_with_offset(element,40+72*(i-1),73).click().perform()
                else :
                    i -= 4
                    ActionChains(self.browser).move_to_element_with_offset(element,40+72*(i-1),145).click().perform()
        except:
            print('元素不可选!')

    def main(self):
        self.get_touclick_img()
        self.move()

BuyTicket.py
实现抢票以及买票,这里已南昌到无锡为例子设置的

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait

import time

# value_tostation = '%u65E0%u9521%u4E1C%2CWGH'  # 终点站(无锡东)
# value_fromstation = '%u5357%u660C%u897F%2CNXG'  # 始发站(南昌西)
value_fromstation = '%u65E0%u9521%u4E1C%2CWGH'  # 终点站(无锡东)
value_tostation = '%u5357%u660C%u897F%2CNXG'  # 始发站(南昌西)

class BuyTickets():
    def __init__(self, driver,sit_type ,train, set_man_index, data):
        self.driver = driver
        self.login_url = 'https://kyfw.12306.cn/otn/login/init'
        self.login_success_url = 'https://kyfw.12306.cn/otn/view/index.html'
        self.ticket_url = 'https://kyfw.12306.cn/otn/leftTicket/init'
        self.person_info_url = 'https://kyfw.12306.cn/otn/confirmPassenger/initDc'
        self.pay_page = 'https://kyfw.12306.cn/otn//payOrder'
        self.train = train  # 车次
        self.set_man_index = set_man_index  # 乘坐人是你默认的第几个位置
        self.sit_type = sit_type    # 一等座二等座等
        self.data = data

    def get_login_info(self):
        with open('info.txt', 'r') as f:
            lines = f.readlines()
            username = lines[0].split()
            password = lines[1].split()
        f.close()
        return [username, password]

    def get_cookie(self):
        with open('cookie.txt', 'r') as f:
            cookie = f.read()
        f.close()
        print(cookie)
        return eval(cookie)

    def login_by_cookie(self):
        self.driver.get(self.login_url)
        self.driver.maximize_window()  # 最大化
        cookie = self.get_cookie()
        self.driver.add_cookie(cookie)
        self.driver.refresh()
        while True:
            if self.driver.current_url == self.login_success_url:
                print('----------->登录成功')
                break
            else:
                print('----------->正在等待跳转')

    def search_tickets(self):
        self.driver.get(self.ticket_url)    # 点击订票网页
        self.driver.add_cookie({"name": "_jc_save_fromStation", "value": value_fromstation})    # 出发站
        self.driver.add_cookie({"name": "_jc_save_toStation", "value": value_tostation})    # 目的地
        self.driver.add_cookie({"name": "_jc_save_fromDate", "value": self.data})  # 时间
        self.driver.refresh()   # 刷新

    def buy_ticket(self):
        i = 0
        flag = True
        while flag:
            time.sleep(1)
            WebDriverWait(self.driver, 10).until(EC.presence_of_element_located((By.XPATH, '//a[@id="query_ticket"]')))
            self.driver.find_element_by_id('query_ticket').click()
            try:    # 判断车次
                WebDriverWait(self.driver, 10).until(EC.presence_of_element_located((By.XPATH,"//a[text()='%s']" % self.train)))
            except:
                if self.driver.find_element_by_xpath("//p[text()='查询超时,请稍后再试!']"):
                    continue
                else:
                    print('兄弟你是不是填错了车次了,没找到车次%s' % self.train)
                    flag = False
            sit = {'商务座':'2',   # 判断一等座二等座等
                   '一等座':'3',
                   '二等座':'4',
                   '高级软卧':'5',
                   '软卧一等卧':'6',
                   '动卧':'7',
                   '硬卧二等卧':'8',
                   '软座':'9',
                   '硬座':'10',
                   '无座':'11',
                   '其他':'12',
                    }
            for name, value in sit.items():
                if name == self.sit_type:
                    text = self.driver.find_element_by_xpath("//a[text()='%s']/../../../../../td[%s]" % (self.train, value)).text
                    print('你关注的票的状态是%s' % text)
                    if text == '*' or text == '无' or text == '候补':
                        continue
                    elif text == '--':
                        print('该车次没有这个座位类型吧')
                        flag = False
                    else:
                        book_button = WebDriverWait(self.driver, 10).until(EC.presence_of_element_located(
                            (By.XPATH, "//a[text()='%s']/../../../../..//a[@class='btn72']" % self.train)))
                        book_button.click()  # 点击预定
                        print('-------------------->抢到票了,正在进入填写乘客信息界面')
                        flag = False
            i = i + 1
            print('抢票%s次' %i)
        while True:
            if self.driver.current_url == self.person_info_url:
                print('页面成功跳转到乘客信息界面')
                break
            else:
                print('等待进入填写乘客信息界面....')
        set_index = WebDriverWait(self.driver, 10).until(EC.presence_of_element_located((By.XPATH,"//input[@id='normalPassenger_%s']" % self.set_man_index)))
        set_index.click()   # 选中乘坐人的次序
        self.driver.find_element_by_id('seatType_1')    # 选择座位
        self.driver.find_element_by_xpath("//option[contains(text(),'%s')]" % self.sit_type)    # 选择
        self.driver.find_element_by_xpath('//*[@id="submitOrder_id"]').click()  # 提交订单
        WebDriverWait(self.driver,10).until(EC.visibility_of_element_located((By.XPATH, "//a[@class='btn92s' and @id='qr_submit_id']")))
        self.driver.find_element_by_xpath("//a[@class='btn92s' and @id='qr_submit_id']").click()
        print('成功抢票')
        while True:
            if self.pay_page in self.driver.current_url:
                print('老铁,需要你付款了!')
                break
            else:
                print('正在跳转到付款界面....')

    def main(self):
        self.login_by_cookie()
        self.search_tickets()
        self.buy_ticket()


if __name__ == '__main__':

    # 分别填写“几等座”
    # 车次
    # 坐车的是在联系人里排第几
    # 出发日期
    buy = BuyTickets(webdriver.Chrome(),'二等座', 'G1377', '0', '2019-10-04')
    begin = time.time()
    buy.main()
    end = time.time()
    print('耗时%s' % (end-begin))



除此之外,还有info.txt文件,里面保存了自己12306里的用户名和密码,这里我就不贴出来了。。。
还有个cookie.txt文件,里面保存的是12306的登录cookie

前提条件:
1,不能输错火车车次
2,联系人排位置从0开始,不能输错
3,座位分一等座二等座还有硬座硬卧巴拉巴拉不能填错
4,此脚本没有选择学生座,也没有选ABCDE座位号
运行方式:
1,先运行login_for_cookie.py进行相关登录获取cookie
2,再运行BuyTocket.py进行抢票购票

你可能感兴趣的:(python+selenium+request实行全自动12306抢票和购票)