|
|
@@ -8,34 +8,7 @@ from datetime import datetime
|
|
|
from cachetools import TTLCache
|
|
|
import pickle
|
|
|
import multiprocessing
|
|
|
-
|
|
|
-cache = None;
|
|
|
-cache_file_path = 'elife.cache.pickle';
|
|
|
-def init_cache():
|
|
|
- global cache;
|
|
|
- if os.path.exists(cache_file_path):
|
|
|
- # 从文件中加载缓存对象
|
|
|
- with open(cache_file_path, 'rb') as file:
|
|
|
- cache = pickle.load(file);
|
|
|
- else:
|
|
|
- cache = TTLCache(maxsize=100, ttl=60*60*24);
|
|
|
- # 将缓存对象持久化到文件
|
|
|
- with open(cache_file_path, 'wb') as file:
|
|
|
- pickle.dump(cache, file);
|
|
|
- return cache;
|
|
|
-
|
|
|
-def save_cache():
|
|
|
- global cache;
|
|
|
- with open(cache_file_path, 'wb') as file:
|
|
|
- pickle.dump(cache, file);
|
|
|
-
|
|
|
-def set_cache(key, value):
|
|
|
- global cache;
|
|
|
- cache[key] = value;
|
|
|
-
|
|
|
-def get_cache(key):
|
|
|
- global cache;
|
|
|
- return cache.get(key);
|
|
|
+from multiprocessing import Manager, Pool
|
|
|
|
|
|
def read_csv(filename='results.csv'):
|
|
|
data = []
|
|
|
@@ -59,6 +32,37 @@ def read_json(filename='results.json'):
|
|
|
# print(data);
|
|
|
return data;
|
|
|
|
|
|
+g_shared_cache = None;
|
|
|
+class SharedCache:
|
|
|
+ cache_file_path = 'elife.cache.pickle';
|
|
|
+ def __init__(self):
|
|
|
+ self.init();
|
|
|
+
|
|
|
+ def init(self):
|
|
|
+ cache = None;
|
|
|
+ cache_file_path = SharedCache.cache_file_path;
|
|
|
+ if os.path.exists(cache_file_path):
|
|
|
+ # 从文件中加载缓存对象
|
|
|
+ with open(cache_file_path, 'rb') as file:
|
|
|
+ cache = pickle.load(file);
|
|
|
+ else:
|
|
|
+ cache = TTLCache(maxsize=100, ttl=60*60*24);
|
|
|
+ # 将缓存对象持久化到文件
|
|
|
+ with open(cache_file_path, 'wb') as file:
|
|
|
+ pickle.dump(cache, file);
|
|
|
+ self.cache = cache;
|
|
|
+
|
|
|
+ def save(self):
|
|
|
+ cache_file_path = SharedCache.cache_file_path;
|
|
|
+ with open(cache_file_path, 'wb') as file:
|
|
|
+ pickle.dump(self.cache, file);
|
|
|
+
|
|
|
+ def set(self, key, value):
|
|
|
+ self.cache[key] = value;
|
|
|
+
|
|
|
+ def get(self, key):
|
|
|
+ return self.cache.get(key);
|
|
|
+
|
|
|
class OfpayGrabber:
|
|
|
CheckBuyRepeatEnable = True;
|
|
|
FastModeEnable = True;
|
|
|
@@ -96,10 +100,10 @@ class OfpayGrabber:
|
|
|
'Referer': 'https://market-web.ofpay.com/h5/union/standard/interactiveIGoChoose/index',
|
|
|
'Cookie': cookies_str,
|
|
|
};
|
|
|
- # print(self.headers);
|
|
|
|
|
|
def start(self):
|
|
|
ret_code = self.check_refresh_token();
|
|
|
+ print(f"账号[{self.accout_id}]token数据状态:{ret_code}");
|
|
|
if ret_code < 0:
|
|
|
print(f"账号[{self.accout_id}]token已失效");
|
|
|
return;
|
|
|
@@ -125,7 +129,7 @@ class OfpayGrabber:
|
|
|
all_ret_list.extend(buy_ret_list);
|
|
|
sort_num += 1;
|
|
|
if len(all_ret_list):
|
|
|
- save_cache();
|
|
|
+ g_shared_cache.save();
|
|
|
return all_ret_list;
|
|
|
|
|
|
def check_refresh_token(self, force_refresh=False):
|
|
|
@@ -249,7 +253,7 @@ class OfpayGrabber:
|
|
|
now_string = datetime.now().strftime('%Y-%m-%d %H:%M:%S');
|
|
|
|
|
|
if OfpayGrabber.CheckBuyRepeatEnable:
|
|
|
- last_buy_succ_date = get_cache(check_buy_repeat_key);
|
|
|
+ last_buy_succ_date = g_shared_cache.get(check_buy_repeat_key);
|
|
|
if now_string == last_buy_succ_date:
|
|
|
print(f"商品[{item_name}]今日已抢购成功过,跳过~~");
|
|
|
return one_ret;
|
|
|
@@ -262,14 +266,14 @@ class OfpayGrabber:
|
|
|
one_ret = self.item_buy_fast(activity_id, sub_activity_id, sub_login_type, award_data);
|
|
|
if one_ret:
|
|
|
# 抢购成功
|
|
|
- set_cache(check_buy_repeat_key, now_string);
|
|
|
+ g_shared_cache.set(check_buy_repeat_key, now_string);
|
|
|
else:
|
|
|
print("库存不足,跳过~");
|
|
|
else:
|
|
|
one_ret = self.item_buy_fast(activity_id, sub_activity_id, sub_login_type, award_data);
|
|
|
if one_ret:
|
|
|
# 抢购成功
|
|
|
- set_cache(check_buy_repeat_key, now_string);
|
|
|
+ g_shared_cache.set(check_buy_repeat_key, now_string);
|
|
|
break;
|
|
|
else:
|
|
|
for award_data in award_list:
|
|
|
@@ -279,7 +283,7 @@ class OfpayGrabber:
|
|
|
one_ret = self.item_buy_normal(activity_id, sub_activity_id, sub_login_type, award_data);
|
|
|
if one_ret:
|
|
|
# 抢购成功
|
|
|
- set_cache(check_buy_repeat_key, now_string);
|
|
|
+ g_shared_cache.set(check_buy_repeat_key, now_string);
|
|
|
else:
|
|
|
print("库存不足,跳过~");
|
|
|
break;
|
|
|
@@ -305,6 +309,7 @@ class OfpayGrabber:
|
|
|
def get_pay_info(self, activity_id, award_id, goods_id, invitation_code, game_account, event_visitor_id):
|
|
|
url = f'https://{self.host}/h5/union/api/draw/interactiveIGoChoose/{activity_id}?awardId={award_id}&goodsId={goods_id}&invitationCode={invitation_code}&gameAccount={game_account}&eventVisitorId={event_visitor_id}';
|
|
|
print("请求商品预支付数据");
|
|
|
+ print(url);
|
|
|
response = self.get_request(url);
|
|
|
if response.status_code == 200:
|
|
|
try:
|
|
|
@@ -486,9 +491,13 @@ class OfpayGrabber:
|
|
|
response = requests.post(url, data=data, headers=self.headers, cookies=self.cookies);
|
|
|
return response;
|
|
|
|
|
|
-def award_grab_worker(account_info, activities_data):
|
|
|
- global cache;
|
|
|
- init_cache();
|
|
|
+def init_data_pre_excute():
|
|
|
+ print('init_shared_data');
|
|
|
+
|
|
|
+def thread_worker_func(index, shared_namespace, account_info, activities_data):
|
|
|
+ print(f'thread_worker_func#{index}');
|
|
|
+ global g_shared_cache;
|
|
|
+ g_shared_cache = shared_namespace.g_shared_cache;
|
|
|
print('########账号[%s]开始抢券工作########' % account_info['account']);
|
|
|
grabber = OfpayGrabber(account_info, activities_data);
|
|
|
results = grabber.start();
|
|
|
@@ -496,18 +505,27 @@ def award_grab_worker(account_info, activities_data):
|
|
|
return f"账号[{account_info['account']}]任务完成";
|
|
|
|
|
|
def main():
|
|
|
+ global g_shared_cache;
|
|
|
+ g_shared_cache = SharedCache();
|
|
|
+ g_shared_cache.set('test', 10);
|
|
|
cpu_threads = multiprocessing.cpu_count();
|
|
|
print(f"CPU支持 {cpu_threads} 个线程/核心");
|
|
|
activities_data = read_json('elife_activities_data.json');
|
|
|
accout_data = read_csv('elife_accout_data.csv');
|
|
|
- cpu_threads = 0;
|
|
|
if cpu_threads > 1:
|
|
|
# 创建进程池
|
|
|
- pool = multiprocessing.Pool(cpu_threads);
|
|
|
+ manager = Manager();
|
|
|
+ # 创建共享命名空间
|
|
|
+ shared_namespace = manager.Namespace();
|
|
|
+ shared_namespace.g_shared_cache = g_shared_cache;
|
|
|
+
|
|
|
+ pool = multiprocessing.Pool(cpu_threads, initializer=init_data_pre_excute);
|
|
|
results = [];
|
|
|
+ index = 0;
|
|
|
for item in accout_data:
|
|
|
- result = pool.apply_async(award_grab_worker,(item, activities_data,));
|
|
|
+ result = pool.apply_async(thread_worker_func,(index, shared_namespace, item, activities_data,));
|
|
|
results.append(result);
|
|
|
+ index += 1;
|
|
|
# 关闭进程池,不再接受新的任务
|
|
|
pool.close();
|
|
|
# 等待所有任务完成
|
|
|
@@ -515,8 +533,6 @@ def main():
|
|
|
# for result in results:
|
|
|
# print(result.get());
|
|
|
else:
|
|
|
- global cache;
|
|
|
- init_cache();
|
|
|
for item in accout_data:
|
|
|
print('########账号[%s]开始抢券工作########' % item['account']);
|
|
|
grabber = OfpayGrabber(item, activities_data);
|