侯体宗的博客
  • 首页
  • Hyperf版
  • beego仿版
  • 人生(杂谈)
  • 技术
  • 关于我
  • 更多分类
    • 文件下载
    • 文字修仙
    • 中国象棋ai
    • 群聊
    • 九宫格抽奖
    • 拼图
    • 消消乐
    • 相册

Python + selenium + requests实现12306全自动抢票及验证码破解加自动点击功能

Python  /  管理员 发布于 7年前   187

测试结果: 

整个买票流程可以再快一点,不过为了稳定起见,有些地方等待了一些时间

完整程序,拿去可用

整个程序分了三个模块:购票模块(主体)、验证码识别模块、余票查询模块

购票模块:

from selenium import webdriverfrom selenium.webdriver.common.by import By from selenium.webdriver.support import expected_conditions as EC from selenium.common.exceptions import NoSuchElementException, StaleElementReferenceException, ElementNotVisibleExceptionimport timeimport requestsfrom urllib.parse import urlencodefrom pyquery import PyQuery as pqfrom check_ticket import Checkfrom verify import Codeimport jsonclass Buy_Ticket():  def __init__(self, start_station, end_station, date, username, password, purpose):    self.num = 1    self.start = start_station    self.end = end_station    self.date = date    self.username = username    self.password = password    self.purpose = purpose    self.login_url = 'https://kyfw.12306.cn/otn/login/init'    self.ticket_url = 'https://kyfw.12306.cn/otn/leftTicket/init'  def login(self):    browser.get(self.login_url)    try:      input_name = browser.find_element_by_id('username')      input_pd = browser.find_element_by_id('password')      button = browser.find_element_by_id('loginSub')      time.sleep(1)      input_name.send_keys(self.username)      input_pd.send_keys(self.password)      c = Code(browser)    #调用验证码识别模块      c.main()      button.click()      time.sleep(2)      #等待页面跳转,如果验证码识别错误,就执行下面的while语句      while browser.current_url == self.login_url + '#':        c = Code(browser)        c.main()        button.click()        time.sleep(2)      #self.get_passenger()      self.check()    except NoSuchElementException:      self.login()  def check(self):    #调用余票查询模块    check = Check(self.date, self.start, self.end, self.purpose)    start_end = check.look_up_station()    self.num = check.get_info()    #cookie的添加,json.dumps把以汉字形式呈现的起始、终点站转化成unicode编码,可在审查元素里查看cookie    browser.add_cookie({'name':'_jc_save_fromStation', 'value':json.dumps(self.start).strip('"').replace('\\', '%') + '%2C' + start_end[0]})    browser.add_cookie({'name':'_jc_save_toStation', 'value':json.dumps(self.end).strip('"').replace('\\', '%') + '%2C' + start_end[1]})    browser.add_cookie({'name':'_jc_save_fromDate', 'value':self.date})    browser.get(self.ticket_url)    if self.purpose == '学生':      btn = browser.find_element_by_id('sf2')      time.sleep(1)      btn.click()    button = browser.find_element_by_id('query_ticket')    time.sleep(1)    button.click()  def book_ticket(self):    print('开始预订车票...')    #先查找出所有车次对应的预订按钮,再根据余票查询模块返回的车次序号,点击相应的预订按钮    button = browser.find_elements_by_class_name('btn72')    button[self.num-1].click()    time.sleep(3)    button2 = browser.find_element_by_id('normalPassenger_0') #按实际情况,可自行修改,这里就选择的第一个常用联系人,          #第二个是normalPassenger_1,依此类推    button2.click()    button3 = browser.find_element_by_id('submitOrder_id')    time.sleep(1)    button3.click()    time.sleep(3) #等待页面加载完毕,不然后面可能会报错,等待时间自行决定    try:      button4 = browser.find_element_by_id('qr_submit_id')      button4.click()    except ElementNotVisibleException:      button4 = browser.find_element_by_id('qr_submit_id')      button4.click()    print('车票预定成功!请在30分钟内完成付款!')  def main(self):    self.login()    self.book_ticket()if __name__ == '__main__':  begin = time.time()  browser = webdriver.Chrome()  b = Buy_Ticket('上海', '重庆', '2018-09-18', '账号', '密码', 'ADULT') #账号、密码自行修改  b.main()  end = time.time()  print('总耗时:%d秒' % int(end-begin))  #browser.close()

验证码识别模块:

import requestsfrom PIL import Imagefrom selenium.webdriver import ActionChainsimport timefrom io import BytesIOclass 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-img-par')    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):    files = {'file': open('captcha.png', 'rb')}       #打开保存到本地的验证码图片    response = requests.post(self.verify_url, files=files)    num = response.text.split('<B>')[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()

余票查询模块:

 

import requestsfrom urllib.parse import urlencodeclass Check():  def __init__(self, date, start, end, purpose):    self.base_url = 'https://kyfw.12306.cn/otn/leftTicket/queryA?'    self.url = 'https://kyfw.12306.cn/otn/resources/js/framework/station_name.js?station_version=1.9018'    self.date = date    self.start_station = start    self.end_station = end    if purpose == '学生':      self.purpose = '0X00'    else:      self.purpose = purpose    #查找出车站的英文简称,用于构造cookie、完整的余票查询链接  def look_up_station(self):    response1 = requests.get(self.url)    a = response1.text.split('@')    a.pop(0)    for each in a:      i = each.split('|')      if self.start_station == i[1]:        self.start_station = i[2]      elif self.end_station == i[1]:        self.end_station = i[2]    return [self.start_station, self.end_station]  def get_info(self):    start_end = self.look_up_station()    #构造请求参数    data = {    'leftTicketDTO.train_date':self.date,    'leftTicketDTO.from_station':start_end[0],    'leftTicketDTO.to_station':start_end[1],    'purpose_codes':self.purpose    }    url = self.base_url + urlencode(data)    response = requests.get(url)    json = response.json()    maps = json['data']['map']    count = 0    #用于对车次编号           for each in json['data']['result']:      count += 1      s = each.split('|')[3:]      info = {      'train':s[0],      'start_end':maps[s[3]] + '-' + maps[s[4]],      'time':s[5] + '-' + s[6],      '历时':s[7],      '一等座':s[-5],      '二等座':s[-6]      }      try:        #余票的结果有3种:有、一个具体的数字(如:18、6等)、无,判断如果余票是有或者一个具体的数字就直接输出对应的车次信息,然后返回        if info['二等座'] == '有' or int(info['二等座']): print('[%d]' % count, info)          return count      except ValueError:        continue   

总结

以上所述是小编给大家介绍的Python + selenium + requests实现12306全自动抢票及验证码破解加自动点击功能,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对站的支持!


  • 上一条:
    利用Python如何实现一个小说网站雏形
    下一条:
    python+selenium实现自动抢票功能实例代码
  • 昵称:

    邮箱:

    0条评论 (评论内容有缓存机制,请悉知!)
    最新最热
    • 分类目录
    • 人生(杂谈)
    • 技术
    • linux
    • Java
    • php
    • 框架(架构)
    • 前端
    • ThinkPHP
    • 数据库
    • 微信(小程序)
    • Laravel
    • Redis
    • Docker
    • Go
    • swoole
    • Windows
    • Python
    • 苹果(mac/ios)
    • 相关文章
    • 在python语言中Flask框架的学习及简单功能示例(0个评论)
    • 在Python语言中实现GUI全屏倒计时代码示例(0个评论)
    • Python + zipfile库实现zip文件解压自动化脚本示例(0个评论)
    • python爬虫BeautifulSoup快速抓取网站图片(1个评论)
    • vscode 配置 python3开发环境的方法(0个评论)
    • 近期文章
    • 在windows10中升级go版本至1.24后LiteIDE的Ctrl+左击无法跳转问题解决方案(0个评论)
    • 智能合约Solidity学习CryptoZombie第四课:僵尸作战系统(0个评论)
    • 智能合约Solidity学习CryptoZombie第三课:组建僵尸军队(高级Solidity理论)(0个评论)
    • 智能合约Solidity学习CryptoZombie第二课:让你的僵尸猎食(0个评论)
    • 智能合约Solidity学习CryptoZombie第一课:生成一只你的僵尸(0个评论)
    • 在go中实现一个常用的先进先出的缓存淘汰算法示例代码(0个评论)
    • 在go+gin中使用"github.com/skip2/go-qrcode"实现url转二维码功能(0个评论)
    • 在go语言中使用api.geonames.org接口实现根据国际邮政编码获取地址信息功能(1个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf分页文件功能(0个评论)
    • gmail发邮件报错:534 5.7.9 Application-specific password required...解决方案(0个评论)
    • 近期评论
    • 122 在

      学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..
    • 123 在

      Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..
    • 原梓番博客 在

      在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..
    • 博主 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..
    • 1111 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
    • 2016-10
    • 2016-11
    • 2018-04
    • 2020-03
    • 2020-04
    • 2020-05
    • 2020-06
    • 2022-01
    • 2023-07
    • 2023-10
    Top

    Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号 PHP交流群

    侯体宗的博客