# -*- coding:utf-8 -*- import threading from requestUtil import myRequests import weChatUtil from bs4 import BeautifulSoup import re import json import time import datetime import chaojiying import randomStr import log class tuiPiao(threading.Thread): def __init__(self, setting): threading.Thread.__init__(self) self.setting=setting self.userName = setting.get("userName") self.userPwd = setting.get("userPwd") self.idCustomer = setting.get("idCustomer") self.goodsid = setting.get("goodsid") self.blocks = setting.get("blocks") self.block = None self.playDay = setting.get("playDay") self.ticketTotal = int(setting.get("ticketTotal")) self.Delivery = str(setting.get("Delivery")) self.sleepTime = int(setting.get("sleepTime"))/1000 self.idTime = setting.get("idTime") self.idHall = setting.get("idHall") self.startTime = setting.get("startTime") self.etcFee = {"EtcFees": "69#1000^", "EtcFeeAmount": 1000} self.captchaInfo={ "key": '', "result": '' } self.req = myRequests() def __login(self): time.sleep(self.sleepTime) Referer = "https://www.yes24.com/Templates/FTLogin.aspx" log.debug("{}开始执行登陆".format(self.userName)) loginData = { "SMemberID": self.userName, "SMemberPassword": self.userPwd, "LoginType": "", "AutoLogin": 1, "FBLoginSub$ReturnParams": "", "FBLoginSub$ReturnURL": "", "RefererUrl": "http://ticket.yes24.com/", "LoginIDSave": "N", "FBLoginSub$NaverCode": "", "FBLoginSub$NaverState": "", "FBLoginSub$Facebook": "" } r=self.req.post("https://www.yes24.com/Templates/FTLogin.aspx", postData=loginData,postReferer=Referer) if r[0:20].find(' 0: log.info("{}时间未到。睡眠{}秒".format(self.userName, offset)) time.sleep(offset-0.3) # 考虑网络延迟 少睡0.3秒 def __waiteToLogin(self): servertime = self.__getServerTime() servertime = datetime.datetime.strptime( servertime, '%a, %d %b %Y %H:%M:%S GMT')+datetime.timedelta(hours=9) # 韩国在东9区 starttime = datetime.datetime.strptime( "{} GMT".format(self.startTime), "%Y%m%d %H:%M:%S GMT") # 韩国的售票时间 offset = time.mktime(starttime.timetuple()) - \ time.mktime(servertime.timetuple()) offset=offset-1800 if offset > 0: log.info("{}时间未到。睡眠{}分钟后登陆".format(self.userName, offset//60)) time.sleep(offset) def __initDeliveryInfo(self): time.sleep(self.sleepTime) log.info("{}开始获取delivery信息".format(self.userName)) r = self.req.post("http://ticket.yes24.com/Pages/Perf/Sale/Ajax/Perf/DeliveryUserInfo.aspx", postReferer="http://ticket.yes24.com/Pages/Perf/Sale/PerfSaleProcess.aspx?IdPerf={}&IdTime=".format(self.goodsid)) soup = BeautifulSoup(r, 'lxml') deliveryList = soup.select('input') deliveryInfo={} for i in deliveryList: deliveryInfo[i.get("id")]=i.get("value") self.deliveryInfo=deliveryInfo def __initIdCustomer(self): time.sleep(self.sleepTime) Referer = "http://ticket.yes24.com/Pages/Perf/Sale/PerfSaleProcess.aspx?IdPerf={}&IdTime={}".format(self.goodsid,self.idTime) d = { "idTime": self.idTime, "idHall": self.idHall, "block": self.blocks[0],#退票比较特殊 获取ID时还没有具体的block "stMax": 10, "pHCardAppOpt": 0 } r = self.req.get( "http://ticket.yes24.com/Pages/Perf/Sale/PerfSaleHtmlSeat.aspx", getData=d, getReferer=Referer) begin = r.find("var IdCustomer") end = begin+28 targetStr = r[begin:end] idCustomer = re.sub(r"\D", "", targetStr) log.warning("***注意***{}的idCustomer为{} 请保存".format(self.userName, self.idCustomer)) self.idCustomer= idCustomer def __getServerTime(self): time.sleep(self.sleepTime) return self.req.getServerTime("http://ticket.yes24.com") def __doLock(self,seatValue): time.sleep(self.sleepTime) lockData = { "name": self.idCustomer, "idTime": self.idTime, "token": seatValue, "Block": self.block } log.debug("{}开始对{}进行锁票".format(self.userName, seatValue)) Referer = "http://ticket.yes24.com/Pages/Perf/Sale/PerfSaleHtmlSeat.aspx?idTime={}&idHall={}".format(self.idTime,self.idHall) lockDataRes = self.req.post("http://ticket.yes24.com/OSIF/Book.asmx/Lock", postData=lockData, postReferer=Referer) if lockDataRes.find('0') > -1: log.debug("{}锁票成功".format(seatValue)) return True else: log.debug("{}锁票失败".format(seatValue)) return False #应该可以省略 def __computeSelectedSeatTotalPrice(self,seatGrade): time.sleep(self.sleepTime) d = { "pIdTime": self.idTime, "PCntClass": seatGrade } Referer = "http://ticket.yes24.com/Pages/Perf/Sale/PerfSaleProcess.aspx?IdPerf={}&IdTime={}".format(self.goodsid,self.idTime) r = self.req.post( "http://ticket.yes24.com/Pages/Perf/Sale/Ajax/Perf/TimeSeatFlashEnd.aspx", postData=d, postReferer=Referer) #
  • 전석 99,000원
  • soup = BeautifulSoup(r, 'lxml') self.classByte = soup.select('div')[0].get('classbyte') selSeatClass = soup.select('#selSeatClass')[0] price = int(selSeatClass.get('price')) seatCount = int(selSeatClass.select( 'option')[0].get('value')) TotalPrice= price*seatCount if self.Delivery == "2" : TotalPrice += 2800 TotalPrice += self.etcFee['EtcFeeAmount'] self.TotalPrice=TotalPrice def __isNeedCaptcha(self): time.sleep(self.sleepTime) d = { "IdPerf": self.goodsid, "IdTime": self.idTime } r = self.req.get( "http://ticket.yes24.com/Pages/Perf/Sale/PerfSaleProcess.aspx", getData=d) if r.find("reCAPTCHAUse = 'Y';") > -1: return True else: return False def __computeCaptchaKeyAndResult(self): time.sleep(self.sleepTime) Referer = "http://ticket.yes24.com/Pages/Perf/Sale/PerfSaleProcess.aspx?IdPerf={}".format(self.goodsid) captchaKeyDataRes = self.req.postJson( "http://ticket.yes24.com/Pages/Perf/Sale/Captcha/CaptchaImage.aspx/GetKeyCaptcha", postReferer=Referer) captchaKey = json.loads(captchaKeyDataRes) captchaKey = captchaKey['d']['Result'] time.sleep(self.sleepTime) imgDataRes = self.req.getImage( "http://ticket.yes24.com/Pages/Perf/Sale/Captcha/CaptchaImage.aspx?key="+captchaKey, getReferer=Referer) captchaFileName = "captchas/cap_"+randomStr.getRandomStr()+".jpeg" with open(captchaFileName, 'wb') as f: f.write(imgDataRes) f.close() keyData = { "key": captchaKey, "result": '' } captchaCount=0 while True: if captchaCount==3: raise Exception("验证码连续三次识别失败") cap=chaojiying.getCaptcha(captchaFileName) if cap=='error': captchaCount+=1 continue else: keyData['result']=cap break self.captchaInfo=keyData def __InicisPayInfo(self): time.sleep(self.sleepTime) d = { "pIdPerf": self.goodsid, "pPrice": self.TotalPrice, "pIdTime":self.idTime, "pHCardAppOpt": 0, "pIsMPoint": 0 } Referer = "http://ticket.yes24.com/Pages/Perf/Sale/PerfSaleProcess.aspx?IdPerf={}".format(self.goodsid) r = self.req.post( "http://ticket.yes24.com/Pages/Perf/Sale/Ajax/Perf/InicisPayInfo.aspx", postData=d, postReferer=Referer) soup = BeautifulSoup(r, 'lxml') inputList = soup.select("input") INicisPay = {} for _input in inputList: INicisPay[_input.get("id")]=_input.get("value") self.INicisPay=INicisPay def __GetBookWhole(self): time.sleep(self.sleepTime) d = { "idHall": self.idHall, "idTime": self.idTime, "block": self.block, "channel": 1, "idCustomer": self.idCustomer, "idOrg": 1 } Referer = "http://ticket.yes24.com/Pages/Perf/Sale/PerfSaleHtmlSeat.aspx?idTime={}&idHall={}".format(self.idTime,self.idHall) r = self.req.post("http://ticket.yes24.com/OSIF/Book.asmx/GetBookWhole", postData=d, postReferer=Referer) soup = BeautifulSoup(r, 'xml') if soup.BlockSeat is None: raise Exception("扫描座位信息异常") return soup.BlockSeat.string def __doBuy(self,seatValue,seatGrade,blockSeat): time.sleep(self.sleepTime) merchantData=[] merchantData.append("ksPayMethod=001000000000") merchantData.append("ksPrice={}".format(self.TotalPrice)) merchantData.append("ksMid={}".format(self.INicisPay["hidMid"])) merchantData.append("ksIdPerf={}".format(self.goodsid)) merchantData.append("ksIdTime={}".format(self.idTime)) merchantData.append("ksTimeOption=2") merchantData.append("ksIdSeat={}".format(seatValue)) merchantData.append("ksIdNonSeat={}-{}".format(self.classByte,seatGrade)) merchantData.append("ksSeatCnt=1") merchantData.append("ksUserMail={}".format(self.INicisPay['hidBuyeremail'])) merchantData.append("ksUserName={}".format(self.INicisPay['hidBuyername'])) merchantData.append("ksUserTel={}".format(self.INicisPay['hidBuyertel'])) merchantData.append("ksUserMobile={}".format(self.INicisPay['hidBuyermobile'])) merchantData.append("ksGoodsName=공연티켓상품") merchantData.append("recaptcha_challenge_field=") merchantData.append("recaptcha_response_field=") merchantData.append("ksEmergencyName={}".format(self.INicisPay['hidBuyername'])) merchantData.append("ksEmergencyTel={}".format(self.INicisPay['hidBuyertel'])) merchantData.append("ksEmergencyMail={}".format(self.INicisPay['hidBuyeremail'])) merchantData.append("ksEtcFee={}".format(self.etcFee['EtcFees'])) merchantData.append("ksEtcValidTicketCnt=1") merchantData.append("ksPayBank=50") merchantData.append("ksIsYesPointYN=N") merchantData.append("captchaText={}".format(self.captchaInfo['result'])) merchantData.append("captchaKey={}".format(self.captchaInfo['key'])) if self.Delivery == "2" : merchantData.append("ksDelivery=8%232800") merchantData.append("ksReceiver={}".format(self.INicisPay['hidBuyername'])) merchantData.append("ksTel={}".format(self.INicisPay['hidBuyertel'])) merchantData.append("ksZipCode={}".format(self.deliveryInfo['LUAddr_ZipCode1'])) merchantData.append("ksAddress={} {}".format(self.deliveryInfo['LUAddr_Address1'],self.deliveryInfo['LUAddr_Address2'])) d = { "merchantData": "&".join(merchantData), "version": "1.0", "currency": "WON", "goodsname": "공연티켓상품", "mid": self.INicisPay['hidMid'], "oid": self.INicisPay['hidOId'], "price": self.TotalPrice, "buyername": self.INicisPay['hidBuyername'], "buyertel": self.INicisPay['hidBuyertel'], "buyeremail": self.INicisPay['hidBuyeremail'], "timestamp": self.INicisPay['hidTimestamp'], "signature": self.INicisPay['hidSignature'], "returnUrl": "http://ticket.yes24.com/Pages/InicisNewPG/INIStdPayResponse.aspx", "closeUrl": "http://ticket.yes24.com/Pages/InicisNewPG/INIStdPayClose.aspx?t=pay", "mKey": self.INicisPay['hidMKey'], "gopaymethod": "Card", "payViewType": "overlay", "quotabase": "2:3:4:5:6:7:8:9:10:11:12", "acceptmethod": "HPP(1):no_receipt:va_receipt:vbanknoreg(0):below1000:popreturn:usespcp:cardpoint" } Referer = "http://ticket.yes24.com/Pages/Perf/Sale/PerfSaleProcess.aspx?IdPerf={}&IdTime={}".format(self.goodsid,self.idTime) r = self.req.post("http://ticket.yes24.com/Pages/InicisNewPG/INIStdPayResponse.aspx", postData=d, postReferer=Referer) if r.find("parent.fts_ProcessSaleFail('');") > 0: sBegin = r.find("fts_ProcessSaleSuccess('") order_id = r[sBegin:(sBegin+41)] order_id = re.sub(r"\D", "", order_id.split("'")[1]) BankAccountInfoData = { "pIdOrder": order_id } time.sleep(self.sleepTime) self.req.post("http://ticket.yes24.com/Pages/Perf/Sale/Ajax/Perf/BankAccountInfo.aspx", postData=BankAccountInfoData, postReferer=Referer) log.info("{}购票成功商品id{}座位:{}".format( self.userName, self.goodsid, blockSeat)) weChatUtil.sendTicketSuccess('yes24',self.goodsid,self.playDay,blockSeat,self.userName) return True else: log.debug("{}购票失败,详见日志".format(self.userName)) return False def __do_ticket(self): # self.__waiteToLogin() self.__login() self.__waiteToStart() if self.idCustomer is None or self.idCustomer == '': self.__initIdCustomer() while self.ticketTotal>0: for self.block in self.blocks: if self.ticketTotal<=0: break blockSeatStr=self.__GetBookWhole() if blockSeatStr is None or blockSeatStr=="": log.info("区域{}无座位".format(self.block)) time.sleep(self.sleepTime) continue blockSeatList = blockSeatStr.split("^") for blockSeat in blockSeatList: if self.ticketTotal<=0: break if blockSeat is None or blockSeat == "": continue _temp = blockSeat.split('@') seatValue = _temp[0] seatGrade = _temp[-1] if self.__doLock(seatValue) is False: continue self.__computeSelectedSeatTotalPrice(seatGrade) if self.__isNeedCaptcha() is True: tryCount=0 while True: if tryCount==3: raise Exception("连续三次尝试购票失败") self.__computeCaptchaKeyAndResult() if tryCount==0: self.__initDeliveryInfo() self.__InicisPayInfo()#获取一次即可 ok=self.__doBuy(seatValue,seatGrade,blockSeat) if ok is False: tryCount+=1 continue else: self.ticketTotal-=1 break else: self.__initDeliveryInfo() self.__InicisPayInfo() ok=self.__doBuy(seatValue,seatGrade,blockSeat) if ok is True: self.ticketTotal-=1#无验证码的 不重试 self.__logout() def run(self): log.debug("开始用账号{}进行抢票.账号配置详情===>{}".format(self.userName,self.setting)) try: self.__do_ticket() except Exception as err: log.error("账号{}抢票出现异常情况====> {}".format(self.userName ,err)) log.info("账号{}结束抢票".format(self.userName))