Python基于selenium的12306模拟登陆+自动抢票

实例:基于selenium的12306模拟登陆+自动抢票

登录页面:https://kyfw.12306.cn/otn/login/init
在这里插入图片描述
查票页面:https://kyfw.12306.cn/otn/leftTicket/init
在这里插入图片描述

分析:

这一篇是对上一篇Python基于selenium的12306模拟登陆的功能拓展,可以实现模拟登陆+自动抢票,考虑到模拟登陆耗时较久且意义不大,所以增加了手动登陆的选项,需要手动点击验证码。抢票时可以自定义的参数包括出发地、目的地、车次、乘坐人和座位类型,当没有余票时将不断刷新页面直到出现余票。该软件由两个.py文件构成,其中ops.py负责对验证码识别并返回识别结果,如果是手动登陆就无需该模块,另外一个main.py为主程序。

程序代码:

main.py:

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver import ActionChains
from ops import getVerifyResult
from PIL import Image
from time import sleep


class Main():
    def __init__(self):
        self.usrname = '你的12306账号'
        self.password = '你的12306密码'
        self.fromStation = "南京"
        self.toStation = "沈阳"
        self.train_date = "2020-05-04"
        self.train = 'G1228'
        self.seat_code = {'一等座': 'M', '二等座': 'O', '硬座': '1',
                          '硬卧': '3', '软卧': '4', '商务座': '9'}
        self.choice = '二等座'
        self.driver = webdriver.Chrome(executable_path='./chromedriver.exe')

    def login(self):
        self.driver.get('https://kyfw.12306.cn/otn/login/init')
        sleep(2)
        self.driver.save_screenshot('main.png')
        img_tag = self.driver.find_element_by_xpath('//*[@id="loginForm"]/div/ul[2]/li[4]/div/div/div[3]/img')
        location = img_tag.location
        size = img_tag.size
        rangle = (int(location['x']) * 1.25, int(location['y']) * 1.25, int(location['x'] + size['width']) * 1.25,
                  int(location['y'] + size['height']) * 1.25)
        img = Image.open('main.png')
        frame = img.crop(rangle)
        frame.save('code.png')
        result = getVerifyResult('code.png')
        for xy in result:
            x = xy[0] * 0.8
            y = xy[1] * 0.8
            ActionChains(self.driver).move_to_element_with_offset(img_tag, x, y).click().perform()
            sleep(1)
        self.driver.find_element_by_id('username').send_keys(self.usrname)
        sleep(1)
        self.driver.find_element_by_id('password').send_keys(self.password)
        sleep(1)
        self.driver.find_element_by_id('loginSub').click()
        while self.driver.current_url == 'https://kyfw.12306.cn/otn/login/init' \
                or self.driver.current_url == 'https://kyfw.12306.cn/otn/login/init#':
            print('等待登陆中...')
            sleep(3)

    def manual_login(self):
        self.driver.get('https://kyfw.12306.cn/otn/login/init')
        self.driver.find_element_by_id('username').send_keys(self.usrname)
        sleep(1)
        self.driver.find_element_by_id('password').send_keys(self.password)
        sleep(1)
        print('请手动点击验证码登陆')
        while self.driver.current_url == 'https://kyfw.12306.cn/otn/login/init'\
                or self.driver.current_url == 'https://kyfw.12306.cn/otn/login/init#':
            print('等待登陆中...')
            sleep(3)

    def queryTicket(self):
        self.driver.get("https://kyfw.12306.cn/otn/leftTicket/init")
        fromStation = self.driver.find_element_by_id('fromStationText')
        fromStation.click()
        fromStation.clear()
        fromStation.send_keys(self.fromStation + '\n')
        toStation = self.driver.find_element_by_id('toStationText')
        toStation.click()
        toStation.clear()
        toStation.send_keys(self.toStation + '\n')
        self.driver.execute_script("document.getElementById('train_date').removeAttribute('readonly')")
        trainDate = self.driver.find_element_by_id("train_date")
        trainDate.clear()
        trainDate.send_keys(self.train_date)
        self.driver.find_element_by_id("query_ticket").click()

    def orderTicket(self):
        WebDriverWait(self.driver, 100).until(
            EC.presence_of_element_located((By.CLASS_NAME, 'number')))
        trains = self.driver.find_elements_by_class_name("number")
        for i, item in enumerate(trains):
            name = item.text
            if name == self.train:
                self.driver.find_elements_by_class_name("btn72")[i].click()
                break
        else:
            print('该日没有指定的车次')
            return
        ul = WebDriverWait(self.driver, 100).until(
                EC.presence_of_element_located((By.ID, 'normal_passenger_id')))
        sleep(1)
        lis = ul.find_elements_by_tag_name('li')
        for i, item in enumerate(lis):
            print("【{}】{}".format(i, item.find_elements_by_tag_name("label")[0].text))
        num = int(input('请选择乘车人:'))
        ul.find_elements_by_tag_name('input')[num].click()
        code = self.seat_code[self.choice]
        seatSelect = self.driver.find_element_by_id("seatType_1")
        print('------余票查询中------')
        count = 1
        flag = False
        while True:
            print('第{}次查询'.format(count))
            count += 1
            for i, item in enumerate(seatSelect.find_elements_by_tag_name("option")):
                if item.get_attribute("value") == code:
                    flag = True
                    item.click()
                    break
            if flag:
                break
            self.driver.back()
            sleep(1)
            self.driver.forward()
            ul = WebDriverWait(self.driver, 100).until(
                    EC.presence_of_element_located((By.ID, 'normal_passenger_id')))
            sleep(1)
            ul.find_elements_by_tag_name('input')[num].click()
            seatSelect = self.driver.find_element_by_id("seatType_1")
        self.driver.find_element_by_id('submitOrder_id').click()
        print('预定成功,请及时付款')

    def __call__(self, *args, **kwargs):
        print('请选择登陆方式:1、自动登陆 2、手动登陆')
        option = input('请选择:')
        if option == '1':
            self.login()
        else:
            self.manual_login()
        self.queryTicket()
        self.orderTicket()


if __name__ == '__main__':
    main = Main()
    main()

ops.py:

import requests
from hashlib import md5


class Chaojiying_Client(object):

    def __init__(self, username, password, soft_id):
        self.username = username
        password = password.encode('utf8')
        self.password = md5(password).hexdigest()
        self.soft_id = soft_id
        self.base_params = {
            'user': self.username,
            'pass2': self.password,
            'softid': self.soft_id,
        }
        self.headers = {
            'Connection': 'Keep-Alive',
            'User-Agent': 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)',
        }

    def PostPic(self, im, codetype):
        """
        im: 图片字节
        codetype: 题目类型 参考 http://www.chaojiying.com/price.html
        """
        params = {
            'codetype': codetype,
        }
        params.update(self.base_params)
        files = {'userfile': ('ccc.jpg', im)}
        r = requests.post('http://upload.chaojiying.net/Upload/Processing.php', data=params, files=files,
                          headers=self.headers)
        return r.json()

    def ReportError(self, im_id):
        """
        im_id:报错题目的图片ID
        """
        params = {
            'id': im_id,
        }
        params.update(self.base_params)
        r = requests.post('http://upload.chaojiying.net/Upload/ReportError.php', data=params, headers=self.headers)
        return r.json()


def transformImgCode(imgPath, imgType):
    chaojiying = Chaojiying_Client('你的超级鹰账号', '你的超级鹰密码', '96001')  # 用户中心>>软件ID 生成一个替换 96001
    im = open(imgPath, 'rb').read()
    return chaojiying.PostPic(im, imgType)['pic_str']


def getVerifyResult(img_path):
    result = transformImgCode(img_path, 9004)
    all_list = []
    if '|' in result:
        list_1 = result.split('|')
        for i in range(len(list_1)):
            xy_list = []
            x = int(list_1[i].split(',')[0])
            y = int(list_1[i].split(',')[1])
            xy_list.append(x)
            xy_list.append(y)
            all_list.append(xy_list)
    else:
        xy_list = []
        x = int(result.split(',')[0])
        y = int(result.split(',')[1])
        xy_list.append(x)
        xy_list.append(y)
        all_list.append(xy_list)

    return all_list


上一篇Python基于selenium的12306模拟登陆:https://blog.csdn.net/Divine0/article/details/105829700

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值