ある投資会社の財テク製品の事前購入を自動的に奪う
60575 ワード
友达はある投資会社の財テク製品の事前購入を自動的に奪うように手伝ってもらいました.
主に2点を学びました.で使用されるターゲットアドレスはモバイル側であり、cookiesはありません.HTTPSヘッダにAuthorizationフィールドを追加し、値が「Bearer」+tokenであることで、ログインユーザを判断します.大体の過程は以下の通りです. はログインアドレスにpostを発行し、ユーザー名とパスワード(json)を持ってtokenを返します. 製品の予約にはユーザ情報が必要なので、まずユーザ情報を取得する:HTTPSヘッダにAuthorizationフィールドを付け、値は‘Bearer’+token(tokenは第1ステップログイン後にサーバが返すtoken値)であり、ユーザ情報を取得したアドレスにgetを発行する. 予約製品:同様にHTTPSヘッダにtokenを持ち込み、ユーザー情報と財テク製品のidをjson dataとして構築し、postを発行する必要があります. 小さな会社ですが、製品の買い取り人はあまり多くありません.毎回手伝う人も多くありません(毎期最大で10人ぐらいです).実は合併しなくてもいいです.見積もってみると、10人も1-2秒のことです.しかし、最終的には同時バージョンを開発し、ちょうどpython asyncio aiohttpを練習した. の概略フローは、ユーザ情報ファイル(jsonフォーマット)を読み取ることによって、すべてのユーザがログインし、情報を取得し、予約する3つの前後プロセスを使用して、共発を使用する. サーバがhttpを使用するため、aiohttpはget、postでverify_を使用する限りSSLエラーをプロンプトします.ssl=Falseでいいです. を併用ものはasyncioである.gather()は、すべてのタスクをtaskにカプセル化して同時実行しました.しかし,タイムアウト再送の処理中に突然呆然とし,併発した場合にどのように再開するか分からなかった.最初はタイムアウトしたリクエストをasyncioに戻す方法を考えていました.loopでは、どうしても結果を得る良い方法はありません.その後、タイムアウト異常(aiohttp.ServerTimeoutError)を処理するときに、await自体という非同期関数を再び処理します.
完全なコードは次のとおりです:user.py
users.py
orderer.py
main.py
主に2点を学びました.
headers = {
'Authorization': 'Bearer ' + token, #token
'Host': 'api.***.com',
'Accept': 'application/json, text/plain, */*',
'Content-Type': 'application/json;charset=UTF-8',
'Referer': 'https://m.***.com',
'Origin': 'https://m.***.com',
'User-Agent': self._get_user_agent()
}
async with aiohttp.ClientSession() as session:
async with session.post(self.urls['order'], json=data, headers=self.headers, verify_ssl=False, timeout=self.time_out) as response:
if response.status == 200:
return await response.json()
完全なコードは次のとおりです:user.py
# -*- coding: utf-8 -*-
import random
import aiohttp
import asyncio
class User:
"""
number:
pwd:
order_amt:
urls: url : url, url, url
semaphore:
time_out:
retry_times:
"""
def __init__(self, number, pwd, order_amt, urls, semaphore, time_out, retry_times):
self.number = number
self.pwd = pwd
self.order_amt = order_amt
self.urls = urls
self.semaphore = semaphore
self.time_out = time_out
self.RETRY_TIMES = retry_times
self.retry = retry_times
self.token = None
self.login_msg = ''
self.headers = {}
self.msg = {}
async def login(self):
""" """
self.retry -= 1
async with self.semaphore:
try:
async with aiohttp.ClientSession() as session:
async with session.post(self.urls['login'], json={'phoneNo': self.number, 'password': self.pwd},
verify_ssl=False, timeout=self.time_out) as response:
if response.status == 200:
return await response.json()
else:
return {'msg': 'response_status {}'.format(response.status)}
except aiohttp.ServerTimeoutError as e:
retry_msg = '{} '.format(self.number)
false_msg = '{} '.format(self.number)
await self._handle_timeout(self.login, self.parse_login, retry_msg, false_msg, e)
except Exception as e:
raise e
def parse_login(self, task):
""" , token, headers"""
self.retry = self.RETRY_TIMES
data = task.result()
self.login_msg = data.get('msg', '')
if self.login_msg == ' ':
self.token = data['data']['token']
self.make_headers()
def _get_user_agent(self):
""" User-Agent"""
USER_AGENT_LIST = [
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36 OPR/26.0.1656.60",
"Opera/8.0 (Windows NT 5.1; U; en)",
"Mozilla/5.0 (Windows NT 5.1; U; en; rv:1.8.1) Gecko/20061208 Firefox/2.0.0 Opera 9.50",
"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; en) Opera 9.50",
"Mozilla/5.0 (Windows NT 6.1; WOW64; rv:34.0) Gecko/20100101 Firefox/34.0",
"Mozilla/5.0 (X11; U; Linux x86_64; zh-CN; rv:1.9.2.10) Gecko/20100922 Ubuntu/10.10 (maverick) Firefox/3.6.10",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/534.57.2 (KHTML, like Gecko) Version/5.1.7 Safari/534.57.2",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36",
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11",
"Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Chrome/10.0.648.133 Safari/534.16",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.101 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.11 TaoBrowser/2.0 Safari/536.11",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.71 Safari/537.1 LBBROWSER",
"Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; LBBROWSER) ",
"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; QQDownload 732; .NET4.0C; .NET4.0E; LBBROWSER)",
"Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; QQBrowser/7.0.3698.400)"
]
return random.choice(USER_AGENT_LIST)
def make_headers(self):
""" requests HTML , token"""
if self.token:
self.headers = {
'Authorization': 'Bearer ' + self.token,
'Host': 'api.***.com',
'Accept': 'application/json, text/plain, */*',
'Content-Type': 'application/json;charset=UTF-8',
'Referer': 'https://m.***.com',
'Origin': 'https://m.***.com',
'User-Agent': self._get_user_agent()
}
async def get_msg(self):
""" """
if self.headers:
self.retry -= 1
async with self.semaphore:
try:
async with aiohttp.ClientSession() as session:
async with session.get(self.urls['getuser'], headers=self.headers,
verify_ssl=False, timeout=self.time_out) as response:
if response.status == 200:
return await response.json()
else:
return {'msg': 'response_status {}'.format(response.status)}
except aiohttp.ServerTimeoutError as e:
retry_msg = '{} '.format(self.number)
false_msg = '{} '.format(self.number)
await self._handle_timeout(self.get_msg, self.parse_msg, retry_msg, false_msg, e)
except Exception as e:
raise e
def parse_msg(self, task):
""" """
self.retry = self.RETRY_TIMES
data = task.result()
msg = data['msg']
if msg == 'success':
self.msg = data['data']
else:
print('get_user_msg server back_error: ', self.number, msg)
raise Exception('get_user_msg server back_error: ', self.number, msg)
async def order(self, product_id):
""" """
if self.headers and self.msg:
self.retry -= 1
data = {
"productId": product_id,
"phoneNo": self.msg.get('phoneNo', ''),
"certNo": self.msg.get('certNo', ''),
"preOrderAmt": self.order_amt,
"bankInfo": self.msg.get('bankInfo', ''),
"bankCode": self.msg.get('bankCode', ''),
"introducer": self.msg.get('introducer', ''),
"custType": self.msg.get('custType', '')
}
async with self.semaphore:
try:
async with aiohttp.ClientSession() as session:
async with session.post(self.urls['order'], json=data, headers=self.headers,
verify_ssl=False, timeout=self.time_out) as response:
if response.status == 200:
return await response.json()
else:
return {'msg': 'response_status {}'.format(response.status)}
except aiohttp.ServerTimeoutError as e:
retry_msg = '{} '.format(self.number)
false_msg = '{} '.format(self.number)
await self._handle_timeout(self.order, self.parse_order, retry_msg, false_msg, e, product_id)
except Exception as e:
raise e
else:
print('{} : '.format(self.number))
raise Exception('{} : '.format(self.number))
def parse_order(self, task):
""" """
self.retry = self.RETRY_TIMES
data = task.result()
print('{} :{}'.format(self.msg['custName'], data['msg']))
async def _handle_timeout(self, func, callback, retry_msg, false_msg, e, para=None):
if self.retry:
print(retry_msg)
if para:
task = asyncio.create_task(func(para))
else:
task = asyncio.create_task(func())
task.add_done_callback(callback)
await task
else:
print(false_msg)
self.retry = self.RETRY_TIMES
raise e
users.py
# -*- coding: utf-8 -*-
import asyncio
from pprint import pp
from .user import User
class Users:
"""
config: : 、 、 、
"""
def __init__(self, config):
self.users = []
self.logined, self.not_logined_msg = [], []
time_out = config['time_out']
retry_times = config['retry_times']
semaphore = asyncio.Semaphore(config['concurrent_num'])
for u in config['users']:
user = User(u['number'], u['pwd'], u['order_amt'], config['urls'], semaphore, time_out, retry_times)
self.users.append(user)
async def login(self):
""" , """
tasks = []
for user in self.users:
task = asyncio.create_task(user.login())
task.add_done_callback(user.parse_login)
tasks.append(task)
await asyncio.gather(*tasks)
self.logined = [user for user in self.users if user.token]
self.not_logined_msg = ['{}: {}'.format(user.number, user.login_msg) for user in self.users if
user.token is None]
if self.not_logined_msg:
print('
:
\t{}'.format('
\t'.join(self.not_logined_msg)))
async def get_logined_users_msg(self):
""" """
tasks = []
for user in self.logined:
task = asyncio.create_task(user.get_msg())
task.add_done_callback(user.parse_msg)
tasks.append(task)
await asyncio.gather(*tasks)
def show_logined_users(self):
""" """
print(' :{} '.format(len(self.logined)))
for user in self.logined:
pp(user.msg)
print('
')
async def order(self, product_id):
""" """
tasks = []
for user in self.logined:
task = asyncio.create_task(user.order(product_id))
task.add_done_callback(user.parse_order)
tasks.append(task)
await asyncio.gather(*tasks)
orderer.py
# -*- coding: utf-8 -*-
from .users import Users
class Orderer:
"""
"""
def __init__(self, config):
self.product_id = ''
self.users = Users(config)
async def go(self):
""" : 、 """
await self.users.login()
await self.users.get_logined_users_msg()
await self.run()
async def run(self):
""" """
while True:
print('
:
\t[1]-
\t[2]- ID
\t[3]- ({})
\t[4]- '.format(self.product_id))
choice = input(' :')
if choice == '1':
self.users.show_logined_users()
elif choice == '2':
self.product_id = input(' ID: ')
elif choice == '3':
if not self.product_id:
print('
*** ID ***')
else:
await self.users.order(self.product_id)
elif choice == '4':
break
else:
print('
*** ***')
main.py
# -*- coding: utf-8 -*-
"""
V3
2020-05-27
: (5 )
2020-05-22
:
: 、urls、
"""
import os
import asyncio
from orderer import Orderer
from tools import init_logger, get_config
logger = init_logger('Production')
config_file = os.path.join(os.path.dirname(__file__), 'config.json')
if __name__ == '__main__':
try:
config = get_config(config_file)
order = Orderer(config)
asyncio.run(order.go())
except Exception as e:
logger.error(e, exc_info=True)
print(e)
input(' ')