diff --git a/.dockerignore b/.dockerignore old mode 100755 new mode 100644 diff --git a/.gitignore b/.gitignore old mode 100755 new mode 100644 diff --git a/README.md b/README.md old mode 100755 new mode 100644 index ef646fa..2f45598 --- a/README.md +++ b/README.md @@ -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代理 diff --git a/TickerConfig.py b/TickerConfig.py index faee155..ab9ad61 100644 --- a/TickerConfig.py +++ b/TickerConfig.py @@ -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" diff --git a/__init__.py b/__init__.py old mode 100755 new mode 100644 diff --git a/agency/__init__.py b/agency/__init__.py old mode 100755 new mode 100644 diff --git a/agency/agency_tools.py b/agency/agency_tools.py old mode 100755 new mode 100644 diff --git a/chromedriver b/chromedriver new file mode 100644 index 0000000..6942445 Binary files /dev/null and b/chromedriver differ diff --git a/config/__init__.py b/config/__init__.py old mode 100755 new mode 100644 diff --git a/config/configCommon.py b/config/configCommon.py old mode 100755 new mode 100644 diff --git a/config/emailConf.py b/config/emailConf.py old mode 100755 new mode 100644 diff --git a/config/logger.py b/config/logger.py old mode 100755 new mode 100644 diff --git a/config/urlConf.py b/config/urlConf.py old mode 100755 new mode 100644 index d74398e..2be91e8 --- a/config/urlConf.py +++ b/config/urlConf.py @@ -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", diff --git a/docker_install_centos.sh b/docker_install_centos.sh old mode 100755 new mode 100644 diff --git a/init/__init__.py b/init/__init__.py old mode 100755 new mode 100644 diff --git a/init/login.py b/init/login.py old mode 100755 new mode 100644 diff --git a/init/select_ticket_info.py b/init/select_ticket_info.py old mode 100755 new mode 100644 index 1dc0142..1494a8a --- a/init/select_ticket_info.py +++ b/init/select_ticket_info.py @@ -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() diff --git a/inter/CheckOrderInfo.py b/inter/CheckOrderInfo.py index 4a20ef4..96d910c 100644 --- a/inter/CheckOrderInfo.py +++ b/inter/CheckOrderInfo.py @@ -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: diff --git a/inter/LiftTicketInit.py b/inter/LiftTicketInit.py index fa61f18..e29f4e7 100644 --- a/inter/LiftTicketInit.py +++ b/inter/LiftTicketInit.py @@ -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 diff --git a/inter/Query.py b/inter/Query.py index 26c04ae..71403a0 100644 --- a/inter/Query.py +++ b/inter/Query.py @@ -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: """ diff --git a/inter/SimulateOrderRequest.py b/inter/SimulateOrderRequest.py new file mode 100644 index 0000000..b98ada3 --- /dev/null +++ b/inter/SimulateOrderRequest.py @@ -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()) + + + \ No newline at end of file diff --git a/inter/SubmitOrderRequest.py b/inter/SubmitOrderRequest.py index ec64d76..d5e5284 100644 --- a/inter/SubmitOrderRequest.py +++ b/inter/SubmitOrderRequest.py @@ -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): diff --git a/inter/easing.py b/inter/easing.py new file mode 100644 index 0000000..622b293 --- /dev/null +++ b/inter/easing.py @@ -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 \ No newline at end of file diff --git a/myException/PassengerUserException.py b/myException/PassengerUserException.py old mode 100755 new mode 100644 diff --git a/myException/ReLoginException.py b/myException/ReLoginException.py new file mode 100644 index 0000000..3a9a3e6 --- /dev/null +++ b/myException/ReLoginException.py @@ -0,0 +1,2 @@ +class ReLoginException(Exception): + pass \ No newline at end of file diff --git a/myException/UserPasswordException.py b/myException/UserPasswordException.py old mode 100755 new mode 100644 diff --git a/myException/__init__.py b/myException/__init__.py old mode 100755 new mode 100644 diff --git a/myException/balanceException.py b/myException/balanceException.py old mode 100755 new mode 100644 diff --git a/myException/ticketConfigException.py b/myException/ticketConfigException.py old mode 100755 new mode 100644 diff --git a/myException/ticketIsExitsException.py b/myException/ticketIsExitsException.py old mode 100755 new mode 100644 diff --git a/myException/ticketNumOutException.py b/myException/ticketNumOutException.py old mode 100755 new mode 100644 diff --git a/myUrllib/__init__.py b/myUrllib/__init__.py old mode 100755 new mode 100644 diff --git a/myUrllib/httpUtils.py b/myUrllib/httpUtils.py old mode 100755 new mode 100644 index 77b2318..453a94c --- a/myUrllib/httpUtils.py +++ b/myUrllib/httpUtils.py @@ -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 diff --git a/requirements-docker37.txt b/requirements-docker37.txt old mode 100755 new mode 100644 diff --git a/requirements.txt b/requirements.txt old mode 100755 new mode 100644 index d4c2d62..c3caf3d --- a/requirements.txt +++ b/requirements.txt @@ -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 \ No newline at end of file +fake-useragent==0.1.11 +pyppeteer +async-timeout \ No newline at end of file diff --git a/run.py b/run.py old mode 100755 new mode 100644 diff --git a/station_name.txt b/station_name.txt old mode 100755 new mode 100644 diff --git a/tkcode.png b/tkcode.png index 0f7695a..2350ac7 100644 Binary files a/tkcode.png and b/tkcode.png differ diff --git a/tmp/__init__.py b/tmp/__init__.py old mode 100755 new mode 100644 diff --git a/tmp/log/__init__.py b/tmp/log/__init__.py old mode 100755 new mode 100644 diff --git a/uml/uml.png b/uml/uml.png old mode 100755 new mode 100644 diff --git a/verify/__init__.py b/verify/__init__.py old mode 100755 new mode 100644