mirror of https://github.com/testerSunshine/12306
parent
d0754e4fcd
commit
e538371e85
|
@ -72,6 +72,11 @@
|
|||
- 开始抢票:`docker-compose up --build -d`
|
||||
- 停止抢票:`docker-compose down`
|
||||
- 查看抢票log: `docker logs --follow ticket`
|
||||
- 关于滑块验证
|
||||
- 下单模式3采用pyppeteer模拟鼠标操作下单,可以过放票时的滑块验证。但目前还不稳定,可能出现进入订单页面时仍需要登陆的情况,原因未知。
|
||||
- 建议将headless设置为False,如果出现问题可以手动操作,特别是在进入订单页面显示需要登陆时,可以手动登陆。
|
||||
- 该功能还在完善中,目前肯定有BUG,请不要过于依赖此功能
|
||||
- **注意:pyppeteer 需要安装hromium (~100MB).脚本会在第一次运行时自动安装,你也可以在跑脚本之前执行pyppeteer-install进行安装**
|
||||
|
||||
#### 目录对应说明
|
||||
- agency - cdn代理
|
||||
|
|
|
@ -9,7 +9,7 @@ TICKET_TYPE = 1
|
|||
|
||||
# 出发日期(list) "2018-01-06", "2018-01-07"
|
||||
STATION_DATES = [
|
||||
"2020-01-18"
|
||||
"2020-02-09"
|
||||
]
|
||||
|
||||
# 填入需要购买的车次(list),"G1353"
|
||||
|
@ -18,10 +18,10 @@ STATION_DATES = [
|
|||
STATION_TRAINS = []
|
||||
|
||||
# 出发城市,比如深圳北,就填深圳就搜得到
|
||||
FROM_STATION = "广州南"
|
||||
FROM_STATION = "海口"
|
||||
|
||||
# 到达城市 比如深圳北,就填深圳就搜得到
|
||||
TO_STATION = "隆回"
|
||||
TO_STATION = "三亚"
|
||||
|
||||
# 座位(list) 多个座位ex:
|
||||
# "商务座",
|
||||
|
@ -33,7 +33,7 @@ TO_STATION = "隆回"
|
|||
# "硬座",
|
||||
# "无座",
|
||||
# "动卧",
|
||||
SET_TYPE = ["二等座"]
|
||||
SET_TYPE = ["二等座","软卧","硬卧"]
|
||||
|
||||
# 当余票小于乘车人,如果选择优先提交,则删减联系人和余票数一致在提交
|
||||
# bool
|
||||
|
@ -56,7 +56,7 @@ IS_AUTO_CODE = True
|
|||
|
||||
# 设置2本地自动打码,需要配置tensorflow和keras库,3为云打码,由于云打码服务器资源有限(为2h4C的cpu服务器),请不要恶意请求,不然只能关闭服务器
|
||||
# ps: 请不要一直依赖云服务器资源,在此向所有提供服务器同学表示感谢
|
||||
AUTO_CODE_TYPE = 3
|
||||
AUTO_CODE_TYPE = 2
|
||||
|
||||
# 此处设置云打码服务器地址,如果有自建的服务器,可以自行更改
|
||||
HOST = "120.77.154.140:8000"
|
||||
|
@ -80,12 +80,12 @@ HTTP_TYPE = "http"
|
|||
# password: "授权码"
|
||||
# host: "smtp.qq.com"
|
||||
EMAIL_CONF = {
|
||||
"IS_MAIL": True,
|
||||
"IS_MAIL": False,
|
||||
"email": "",
|
||||
"notice_email_list": "",
|
||||
"username": "",
|
||||
"password": "",
|
||||
"host": "smtp.qq.com",
|
||||
"host": "",
|
||||
}
|
||||
|
||||
# 是否开启 server酱 微信提醒, 使用前需要前往 http://sc.ftqq.com/3.version 扫码绑定获取 SECRET 并关注获得抢票结果通知的公众号
|
||||
|
@ -97,12 +97,17 @@ SERVER_CHAN_CONF = {
|
|||
# 是否开启cdn查询,可以更快的检测票票 1为开启,2为关闭
|
||||
IS_CDN = 1
|
||||
|
||||
# 下单接口分为两种,1 模拟网页自动捡漏下单(不稳定),2 模拟车次后面的购票按钮下单(稳如老狗)
|
||||
ORDER_TYPE = 2
|
||||
# 下单接口分为两种,1 模拟网页自动捡漏下单(不稳定),2 模拟车次后面的购票按钮下单(稳如老狗),3 pyppeteer模拟下单(可以模拟鼠标拖动滑块,但速度较慢,且不稳定)
|
||||
ORDER_TYPE = 3
|
||||
|
||||
# 如果采用pyppeteer下单,可以选择浏览器在前台显示(Flase) 或后台运行(True),前台运行的话,如果有啥BUG可以手动操作,后台显示尚未测试
|
||||
IS_HEADLESS = False
|
||||
|
||||
|
||||
|
||||
# 下单模式 1 为预售,整点刷新,刷新间隔0.1-0.5S, 然后会校验时间,比如12点的预售,那脚本就会在12.00整检票,刷新订单
|
||||
# 2 是捡漏,捡漏的刷新间隔时间为0.5-3秒,时间间隔长,不容易封ip
|
||||
ORDER_MODEL = 1
|
||||
ORDER_MODEL = 2
|
||||
|
||||
# 是否开启代理, 0代表关闭, 1表示开始
|
||||
# 开启此功能的时候请确保代理ip是否可用,在测试放里面经过充分的测试,再开启此功能,不然可能会耽误你购票的宝贵时间
|
||||
|
@ -117,19 +122,17 @@ OPEN_TIME = "12:59:57"
|
|||
# 1=使用selenium获取devicesID
|
||||
# 2=使用网页端/otn/HttpZF/logdevice获取devicesId,这个接口的算法目前可能有点问题,如果登录一直302的请改为配置1
|
||||
# 3=自己打开浏览器在headers-Cookies中抓取RAIL_DEVICEID和RAIL_EXPIRATION,这个就不用配置selenium
|
||||
COOKIE_TYPE = 3
|
||||
COOKIE_TYPE = 1
|
||||
# 如果COOKIE_TYPE=1,则需配置chromeDriver路径,下载地址http://chromedriver.storage.googleapis.com/index.html
|
||||
# chromedriver配置版本只要和chrome的大版本匹配就行
|
||||
CHROME_PATH = "/usr/src/app/chromedriver"
|
||||
CHROME_PATH = "/home/homura/12306/12306dev/12306/chromedriver"
|
||||
|
||||
# 为了docker37 准备的环境变量,windows环境可以不用管这个参数
|
||||
CHROME_CHROME_PATH = "/opt/google/chrome/google-chrome"
|
||||
|
||||
# 如果COOKIE_TYPE=3, 则需配置RAIL_EXPIRATION、RAIL_DEVICEID的值
|
||||
RAIL_EXPIRATION = ""
|
||||
RAIL_DEVICEID = ""
|
||||
# RAIL_EXPIRATION = "1577034103293"
|
||||
# RAIL_DEVICEID = "CDno29Erc_Pf3FSXb4dzq-Op64EhWrsi5yUZKVIKR1MAfYo2qFlCeXD8VkexY7_1qg-ClV-fE8j9jgVlPZxRh3wVc2iqLe_5A8sdr62qZx4B22JPF8lFCjpgTKZ5ODW90HJd5tiQsJ1KR9nOqHRxHj1FT5LEIwfw"
|
||||
RAIL_EXPIRATION = "1577034103293"
|
||||
RAIL_DEVICEID = "CDno29Erc_Pf3FSXb4dzq-Op64EhWrsi5yUZKVIKR1MAfYo2qFlCeXD8VkexY7_1qg-ClV-fE8j9jgVlPZxRh3wVc2iqLe_5A8sdr62qZx4B22JPF8lFCjpgTKZ5ODW90HJd5tiQsJ1KR9nOqHRxHj1FT5LEIwfw"
|
||||
|
||||
|
||||
# 1=>为一直随机ua,2->只启动的时候随机一次ua
|
||||
|
@ -154,4 +157,4 @@ MAX_TIME = 3
|
|||
MIN_TIME = 1
|
||||
|
||||
# 软件版本
|
||||
RE_VERSION = "1.2.004"
|
||||
RE_VERSION = "1.2.005"
|
||||
|
|
Binary file not shown.
|
@ -429,6 +429,19 @@ urls = {
|
|||
"is_cdn": True,
|
||||
"is_json": True,
|
||||
},
|
||||
"leftTicketPage":{ #车票查询页面
|
||||
"req_url": "otn/leftTicket/init?linktypeid=dc&fs={0}&ts={1}&date={2}&flag=N,N,Y",
|
||||
"req_type":"get",
|
||||
"Referer":"",
|
||||
"Content-Type": 1,
|
||||
"Host": "kyfw.12306.cn",
|
||||
"re_try": 10,
|
||||
"re_time": 0.01,
|
||||
"s_time": 0.1,
|
||||
"is_logger": False,
|
||||
"is_cdn": True,
|
||||
"is_json": False
|
||||
},
|
||||
"Pushbear": { # push通知
|
||||
"req_url": "/sub",
|
||||
"req_type": "post",
|
||||
|
|
|
@ -21,6 +21,7 @@ from inter.GetPassengerDTOs import getPassengerDTOs
|
|||
from inter.LiftTicketInit import liftTicketInit
|
||||
from inter.Query import query
|
||||
from inter.SubmitOrderRequest import submitOrderRequest
|
||||
from inter.SimulateOrderRequest import SimulateOrderRequest
|
||||
from myException.PassengerUserException import PassengerUserException
|
||||
from myException.UserPasswordException import UserPasswordException
|
||||
from myException.ticketConfigException import ticketConfigException
|
||||
|
@ -211,6 +212,26 @@ class select:
|
|||
self.passengerTicketStrList, self.oldPassengerStr, train_date,
|
||||
TickerConfig.TICKET_PEOPLES)
|
||||
sor.sendSubmitOrderRequest()
|
||||
elif TickerConfig.ORDER_TYPE == 3: # selenium模拟下单
|
||||
sele = SimulateOrderRequest(selectObj=self,
|
||||
from_station=from_station,
|
||||
to_station=to_station,
|
||||
from_station_h=TickerConfig.FROM_STATION,
|
||||
to_station_h=TickerConfig.TO_STATION,
|
||||
_station_seat=self._station_seat,
|
||||
station_trains=TickerConfig.STATION_TRAINS,
|
||||
station_dates=TickerConfig.STATION_DATES,
|
||||
ticke_peoples_num=len(TickerConfig.TICKET_PEOPLES),
|
||||
train_no = train_no,
|
||||
secretStr = secretStr,
|
||||
set_type = self.set_type,
|
||||
train_date=train_date,
|
||||
passengerTicketStr=self.passengerTicketStrList,
|
||||
oldPassengerStr=self.oldPassengerStr,
|
||||
start_time = queryResult.get("start_time"),
|
||||
)
|
||||
sele.Do_simulate()
|
||||
|
||||
elif secretList: # 候补订单
|
||||
c = chechFace(self, secretList, train_no)
|
||||
c.sendChechFace()
|
||||
|
|
|
@ -2,7 +2,9 @@
|
|||
from collections import OrderedDict
|
||||
from inter.GetQueueCount import getQueueCount
|
||||
from inter.GetRepeatSubmitToken import getRepeatSubmitToken
|
||||
|
||||
import sys
|
||||
from selenium import webdriver
|
||||
from selenium.webdriver.common.keys import Keys
|
||||
|
||||
class checkOrderInfo:
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@ class liftTicketInit:
|
|||
# 获取初始化的结果
|
||||
result = self.session.httpClint.send(urls)
|
||||
# 用正则表达式查出CLeftTicketUrl的值
|
||||
#print(result)
|
||||
matchObj = re.search('var CLeftTicketUrl = \'(.*)\'', result, re.M|re.I);
|
||||
if matchObj:
|
||||
# 如果有值,替换queryUrl
|
||||
|
|
|
@ -150,6 +150,7 @@ class query:
|
|||
"is_more_ticket_num": is_more_ticket_num,
|
||||
"cdn": self.httpClint.cdn,
|
||||
"status": True,
|
||||
"start_time":start_time
|
||||
}
|
||||
elif is_ticket_pass == '无' and ticket_info[37] == "1" and TickerConfig.TICKET_TYPE is 2:
|
||||
"""
|
||||
|
|
|
@ -0,0 +1,214 @@
|
|||
|
||||
import copy
|
||||
import random
|
||||
import wrapcache
|
||||
from config import urlConf
|
||||
from config.TicketEnmu import ticket
|
||||
from config.emailConf import sendEmail
|
||||
from config.serverchanConf import sendServerChan
|
||||
from myUrllib.httpUtils import HTTPClient
|
||||
from config.configCommon import seat_conf_2
|
||||
import TickerConfig
|
||||
import sys
|
||||
import os
|
||||
import time
|
||||
import numpy as np
|
||||
import math
|
||||
|
||||
from myException.ReLoginException import ReLoginException
|
||||
|
||||
from myException.ticketIsExitsException import ticketIsExitsException
|
||||
from myException.ticketNumOutException import ticketNumOutException
|
||||
from selenium.common.exceptions import TimeoutException
|
||||
import inter.easing
|
||||
import asyncio
|
||||
from pyppeteer import launch
|
||||
import async_timeout
|
||||
|
||||
class SimulateOrderRequest:
|
||||
def __init__(self,selectObj,from_station,to_station,from_station_h,to_station_h,_station_seat,station_trains, station_dates, ticke_peoples_num, train_no ,secretStr ,set_type ,train_date, passengerTicketStr, oldPassengerStr,start_time):
|
||||
self.session = selectObj
|
||||
self.urls = urlConf.urls
|
||||
self.from_station = from_station
|
||||
self.to_station = to_station
|
||||
self.from_station_h = from_station_h
|
||||
self.to_station_h = to_station_h
|
||||
self.station_trains = station_trains
|
||||
self._station_seat = _station_seat if isinstance(_station_seat, list) else list(_station_seat)
|
||||
self.station_dates = station_dates if isinstance(station_dates, list) else list(station_dates)
|
||||
self.ticket_black_list = dict()
|
||||
self.ticke_peoples_num = ticke_peoples_num
|
||||
self.train_date = train_date
|
||||
self.secretStr = secretStr
|
||||
self.train_no = train_no
|
||||
self.start_time = start_time
|
||||
self.passengerTicketStr= passengerTicketStr
|
||||
self.oldPassengerStr= oldPassengerStr
|
||||
|
||||
self.set_type = set_type
|
||||
|
||||
|
||||
async def mouse_slide(self,page=None):
|
||||
await asyncio.sleep(0.3)
|
||||
try :
|
||||
#鼠标移动到滑块,按下,滑动到头(然后延时处理),松开按键
|
||||
await self.page.hover('#nc_1_n1z')
|
||||
await self.page.mouse.down()
|
||||
await self.page.mouse.move(2000, 0, {'delay': random.randint(1000, 2000)})
|
||||
await self.page.mouse.up()
|
||||
except Exception as e:
|
||||
print(e, ':验证失败')
|
||||
return False,self.page
|
||||
return True,self.page
|
||||
|
||||
|
||||
|
||||
def get_order_information(self):
|
||||
passengers = []
|
||||
passengerStrList = self.passengerTicketStr.split('_')
|
||||
for eachPassenger in passengerStrList:
|
||||
passengerInfo = eachPassenger.split(',')
|
||||
if (len(passengerInfo) == 9):
|
||||
passengers.append({'type':passengerInfo[0],'name':passengerInfo[3]})
|
||||
return passengers
|
||||
|
||||
async def fill_the_page(self):
|
||||
TIME_OUT_L = 20
|
||||
if TickerConfig.IS_HEADLESS:
|
||||
TIME_OUT_L = 3
|
||||
try:
|
||||
async with async_timeout.timeout(TIME_OUT_L) as cm:
|
||||
while not await self.page.querySelector('#normalPassenger_0'):
|
||||
pass
|
||||
except:
|
||||
if cm.expired: #超时,没能进入订单页,可能是session失效
|
||||
print("超时未能进入订单页面,重试")
|
||||
raise ReLoginException("Need Login")
|
||||
passengers = self.get_order_information()
|
||||
passenger_num = 1
|
||||
for eachPassenger in passengers:
|
||||
xpath = "//label[text() = '{0}']".format(eachPassenger['name'])
|
||||
while not await self.page.querySelector('#normalPassenger_0'):
|
||||
pass
|
||||
a = await self.page.xpath(xpath)
|
||||
await a[-1].click()
|
||||
await self.page.select('select#seatType_'+str(passenger_num),eachPassenger['type'])
|
||||
passenger_num += 1
|
||||
button = await self.page.J("#submitOrder_id")
|
||||
if button:
|
||||
print("不需要滑块验证,尝试提交中")
|
||||
await button.click()
|
||||
#await asyncio.sleep(0.2)
|
||||
|
||||
await self.page.waitForSelector('#qr_submit_id', {'visible':True,})
|
||||
qr_btn = await self.page.J("#qr_submit_id")
|
||||
#asyncio.sleep(120)
|
||||
await qr_btn.click()
|
||||
asyncio.sleep(30)
|
||||
sendEmail(ticket.WAIT_ORDER_SUCCESS.format("1"))
|
||||
sendServerChan(ticket.WAIT_ORDER_SUCCESS.format("1"))
|
||||
raise ticketIsExitsException(ticket.WAIT_ORDER_SUCCESS.format("1"))
|
||||
else:
|
||||
slide = await self.page.J("#nc_1_n1z")
|
||||
if slide:
|
||||
print("需要滑块验证,尝试提交中")
|
||||
flag = False
|
||||
for i in range(3):
|
||||
flag,self.page = await self.mouse_slide(page=self.page) #js拉动滑块过去。
|
||||
if flag:
|
||||
break
|
||||
else:
|
||||
continue
|
||||
await self.page.waitForSelector('#qr_submit_id', {'visible':True,})
|
||||
qr_btn = await self.page.J("#qr_submit_id")
|
||||
await qr_btn.click()
|
||||
asyncio.sleep(30)
|
||||
sendEmail(ticket.WAIT_ORDER_SUCCESS.format("1"))
|
||||
sendServerChan(ticket.WAIT_ORDER_SUCCESS.format("1"))
|
||||
raise ticketIsExitsException(ticket.WAIT_ORDER_SUCCESS.format("1"))
|
||||
else:
|
||||
print("失败:未知原因")
|
||||
return
|
||||
|
||||
|
||||
async def py_delete_all_cookies(self):
|
||||
tcookies = await self.page.cookies()
|
||||
for a in tcookies:
|
||||
await self.page.deleteCookie(a)
|
||||
|
||||
async def py_set_all_cookies(self):
|
||||
c = self.session.httpClint.get_cookie_all_items()
|
||||
#print(c)
|
||||
for x in c:
|
||||
if x[0] == 'RAIL_DEVICEID' or x[0] == 'RAIL_EXPIRATION':
|
||||
await self.page.setCookie({'name':x[0],'value':x[1],'domain':'.12306.cn','path':'/'})
|
||||
elif x[0] == 'JSESSIONID':
|
||||
await self.page.setCookie({'name':x[0],'value':x[1],'path':'/otn','domain': 'kyfw.12306.cn'})
|
||||
else:
|
||||
await self.page.setCookie({'name':x[0],'value':x[1],'domain': 'kyfw.12306.cn'})
|
||||
#print(await self.page.cookies())
|
||||
|
||||
async def I_AM_NOT_A_ROBOT(self):
|
||||
await self.page.evaluate('''() =>{ Object.defineProperties(navigator,{ webdriver:{ get: () => false } }) }''') #以下为插入中间js,将淘宝会为了检测浏览器而调用的js修改其结果。
|
||||
await self.page.evaluate('''() =>{ window.navigator.chrome = { runtime: {}, }; }''')
|
||||
await self.page.evaluate('''() =>{ Object.defineProperty(navigator, 'languages', { get: () => ['en-US', 'en'] }); }''')
|
||||
await self.page.evaluate('''() =>{ Object.defineProperty(navigator, 'plugins', { get: () => [1, 2, 3, 4, 5,6], }); }''')
|
||||
|
||||
await self.page.evaluateOnNewDocument('''() =>{ Object.defineProperties(navigator,{ webdriver:{ get: () => false } }) }''') #以下为插入中间js,将淘宝会为了检测浏览器而调用的js修改其结果。
|
||||
await self.page.evaluateOnNewDocument('''() =>{ window.navigator.chrome = { runtime: {}, }; }''')
|
||||
await self.page.evaluateOnNewDocument('''() =>{ Object.defineProperty(navigator, 'languages', { get: () => ['en-US', 'en'] }); }''')
|
||||
await self.page.evaluateOnNewDocument('''() =>{ Object.defineProperty(navigator, 'plugins', { get: () => [1, 2, 3, 4, 5,6], }); }''')
|
||||
|
||||
async def start_simulate(self):
|
||||
self.driver = await launch({'headless':TickerConfig.IS_HEADLESS ,'args': ['--no-sandbox'], })
|
||||
self.page = await self.driver.newPage()
|
||||
select_url = copy.copy(self.urls["leftTicketPage"])
|
||||
req_url = "https://"+select_url['Host'] +'/'+ select_url['req_url'].format(self.from_station_h+','+self.from_station,self.to_station_h+','+self.to_station,self.train_date)
|
||||
await self.page.setUserAgent('Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36')
|
||||
|
||||
await self.page.goto(req_url)
|
||||
await self.I_AM_NOT_A_ROBOT()
|
||||
while not await self.page.querySelector('#query_ticket'):
|
||||
pass
|
||||
await self.py_delete_all_cookies()
|
||||
try:
|
||||
while await self.page.cookies():
|
||||
pass
|
||||
except:
|
||||
pass
|
||||
await self.py_set_all_cookies()
|
||||
try:
|
||||
while not await self.page.cookies():
|
||||
pass
|
||||
except:
|
||||
pass
|
||||
await self.page.goto(req_url)
|
||||
js = "checkG1234(\'"+self.secretStr+"\',\'"+self.start_time+"\',\'"+self.train_no+"\',\'"+self.from_station+"\',\'"+self.to_station+"\')"
|
||||
await self.page.evaluate(js)
|
||||
try:
|
||||
await self.fill_the_page()
|
||||
except ReLoginException:
|
||||
print("重新登陆中")
|
||||
self.session.call_login()
|
||||
await self.page.goto(req_url)
|
||||
while not await self.page.querySelector('#query_ticket'):
|
||||
pass
|
||||
await self.py_delete_all_cookies()
|
||||
while await self.page.cookies():
|
||||
pass
|
||||
await self.py_set_all_cookies()
|
||||
while not await self.page.cookies():
|
||||
pass
|
||||
await self.page.goto(req_url)
|
||||
await self.page.evaluate(js)
|
||||
try:
|
||||
await self.fill_the_page()
|
||||
except ReLoginException:
|
||||
print("失败,重新查询")
|
||||
return
|
||||
|
||||
def Do_simulate(self):
|
||||
asyncio.get_event_loop().run_until_complete(self.start_simulate())
|
||||
|
||||
|
||||
|
|
@ -9,7 +9,6 @@ from inter.ConfirmHB import confirmHB
|
|||
from inter.PassengerInitApi import passengerInitApi
|
||||
from myException.ticketIsExitsException import ticketIsExitsException
|
||||
|
||||
|
||||
def time():
|
||||
"""
|
||||
获取日期
|
||||
|
@ -74,7 +73,7 @@ class submitOrderRequest:
|
|||
print (u'出票失败')
|
||||
elif 'messages' in submitResult and submitResult['messages']:
|
||||
raise ticketIsExitsException(submitResult['messages'][0])
|
||||
|
||||
|
||||
|
||||
class submitOrderRequestByAfterNate:
|
||||
def __init__(self, session, secretList, tickerNo):
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
# Created by aneasystone on 2018/3/14
|
||||
import numpy as np
|
||||
import math
|
||||
|
||||
|
||||
# https://github.com/gdsmith/jquery.easing/blob/master/jquery.easing.js
|
||||
def ease_in_quad(x):
|
||||
return x * x
|
||||
|
||||
|
||||
def ease_out_quad(x):
|
||||
return 1 - (1 - x) * (1 - x)
|
||||
|
||||
|
||||
def ease_out_quart(x):
|
||||
return 1 - pow(1 - x, 4)
|
||||
|
||||
|
||||
def ease_out_expo(x):
|
||||
if x == 1:
|
||||
return 1
|
||||
else:
|
||||
return 1 - pow(2, -10 * x)
|
||||
|
||||
|
||||
def ease_out_bounce(x):
|
||||
n1 = 7.5625
|
||||
d1 = 2.75
|
||||
if x < 1 / d1 :
|
||||
return n1 * x * x
|
||||
elif x < 2 / d1:
|
||||
x -= 1.5 / d1
|
||||
return n1 * x*x + 0.75
|
||||
elif x < 2.5 / d1:
|
||||
x -= 2.25 / d1
|
||||
return n1 * x*x + 0.9375
|
||||
else:
|
||||
x -= 2.625 / d1
|
||||
return n1 * x*x + 0.984375
|
||||
|
||||
|
||||
def ease_out_elastic(x):
|
||||
if x == 0:
|
||||
return 0
|
||||
elif x == 1:
|
||||
return 1
|
||||
else:
|
||||
c4 = (2 * math.pi) / 3
|
||||
return pow(2, -10 * x) * math.sin((x * 10 - 0.75) * c4) + 1
|
||||
|
||||
|
||||
def get_tracks(distance, seconds, ease_func):
|
||||
tracks = [0]
|
||||
offsets = [0]
|
||||
for t in np.arange(0.0, seconds, 0.1):
|
||||
ease = globals()[ease_func]
|
||||
offset = round(ease(t/seconds) * distance)
|
||||
tracks.append(offset - offsets[-1])
|
||||
offsets.append(offset)
|
||||
return offsets, tracks
|
|
@ -0,0 +1,2 @@
|
|||
class ReLoginException(Exception):
|
||||
pass
|
|
@ -73,6 +73,9 @@ class HTTPClient(object):
|
|||
"""
|
||||
return self._s.cookies.values()
|
||||
|
||||
def get_cookie_all_items(self):
|
||||
return self._s.cookies.items()
|
||||
|
||||
def del_cookies(self):
|
||||
"""
|
||||
删除所有的key
|
||||
|
|
|
@ -12,4 +12,6 @@ matplotlib>=3.0.2
|
|||
numpy>=1.14.6
|
||||
scipy>=1.1.0
|
||||
selenium==3.11.0
|
||||
fake-useragent==0.1.11
|
||||
fake-useragent==0.1.11
|
||||
pyppeteer
|
||||
async-timeout
|
BIN
tkcode.png
BIN
tkcode.png
Binary file not shown.
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 63 KiB After Width: | Height: | Size: 63 KiB |
Loading…
Reference in New Issue