'init'
This commit is contained in:
215
scheduler.py
Normal file
215
scheduler.py
Normal file
@@ -0,0 +1,215 @@
|
||||
import random
|
||||
import time
|
||||
from datetime import datetime, timedelta
|
||||
from typing import List, Dict
|
||||
from threading import Thread, Lock
|
||||
from loguru import logger
|
||||
|
||||
from adspower_client import AdsPowerClient
|
||||
from ad_automation import MIPAdAutomation
|
||||
from data_manager import DataManager
|
||||
from config import Config
|
||||
|
||||
|
||||
class ClickScheduler:
|
||||
"""点击任务调度器"""
|
||||
|
||||
def __init__(self):
|
||||
self.adspower_client = AdsPowerClient()
|
||||
self.data_manager = DataManager()
|
||||
self.running = False
|
||||
self.lock = Lock()
|
||||
|
||||
def add_url(self, url: str) -> bool:
|
||||
"""
|
||||
添加待点击的URL
|
||||
|
||||
Args:
|
||||
url: MIP页面链接
|
||||
|
||||
Returns:
|
||||
是否添加成功
|
||||
"""
|
||||
return self.data_manager.add_url(url)
|
||||
|
||||
def add_urls(self, urls: List[str]) -> int:
|
||||
"""
|
||||
批量添加URL
|
||||
|
||||
Args:
|
||||
urls: URL列表
|
||||
|
||||
Returns:
|
||||
成功添加的数量
|
||||
"""
|
||||
count = 0
|
||||
for url in urls:
|
||||
if self.add_url(url):
|
||||
count += 1
|
||||
return count
|
||||
|
||||
def start_scheduler(self):
|
||||
"""启动调度器"""
|
||||
if self.running:
|
||||
logger.warning("调度器已在运行中")
|
||||
return
|
||||
|
||||
self.running = True
|
||||
logger.info("启动点击调度器")
|
||||
|
||||
# 启动调度线程
|
||||
thread = Thread(target=self._schedule_loop, daemon=True)
|
||||
thread.start()
|
||||
|
||||
def stop_scheduler(self):
|
||||
"""停止调度器"""
|
||||
self.running = False
|
||||
logger.info("停止点击调度器")
|
||||
|
||||
def _schedule_loop(self):
|
||||
"""调度循环"""
|
||||
while self.running:
|
||||
try:
|
||||
# 检查当前时间是否在工作时间内
|
||||
if not self._is_work_time():
|
||||
logger.debug("当前不在工作时间内,等待...")
|
||||
time.sleep(60)
|
||||
continue
|
||||
|
||||
# 获取待处理的URL
|
||||
url = self._get_next_url()
|
||||
|
||||
if url:
|
||||
logger.info(f"开始处理URL: {url}")
|
||||
self._process_url(url)
|
||||
else:
|
||||
logger.debug("暂无待处理的URL,等待...")
|
||||
time.sleep(30)
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"调度循环异常: {str(e)}")
|
||||
time.sleep(10)
|
||||
|
||||
def _is_work_time(self) -> bool:
|
||||
"""
|
||||
检查当前是否在工作时间内
|
||||
|
||||
Returns:
|
||||
是否在工作时间
|
||||
"""
|
||||
now = datetime.now()
|
||||
current_hour = now.hour
|
||||
|
||||
return Config.WORK_START_HOUR <= current_hour < Config.WORK_END_HOUR
|
||||
|
||||
def _get_next_url(self) -> str:
|
||||
"""
|
||||
获取下一个需要处理的URL
|
||||
|
||||
Returns:
|
||||
URL或None
|
||||
"""
|
||||
with self.lock:
|
||||
# 获取所有活跃的URL
|
||||
urls = self.data_manager.get_active_urls()
|
||||
|
||||
for url_data in urls:
|
||||
url = url_data['url']
|
||||
|
||||
# 检查是否已达到随机点击次数上限
|
||||
click_count = url_data.get('click_count', 0)
|
||||
target_clicks = url_data.get('target_clicks', 0)
|
||||
|
||||
if click_count >= target_clicks:
|
||||
# 标记为已完成
|
||||
self.data_manager.mark_url_completed(url)
|
||||
continue
|
||||
|
||||
# 检查距离上次点击是否超过间隔时间
|
||||
last_click_time = url_data.get('last_click_time')
|
||||
if last_click_time:
|
||||
last_click = datetime.fromisoformat(last_click_time)
|
||||
time_diff = datetime.now() - last_click
|
||||
|
||||
if time_diff.total_seconds() < Config.CLICK_INTERVAL_MINUTES * 60:
|
||||
continue
|
||||
|
||||
return url
|
||||
|
||||
return None
|
||||
|
||||
def _process_url(self, url: str):
|
||||
"""
|
||||
处理单个URL的点击任务
|
||||
|
||||
Args:
|
||||
url: 待处理的URL
|
||||
"""
|
||||
page = None
|
||||
|
||||
try:
|
||||
# 启动 AdsPower 浏览器
|
||||
browser_info = self.adspower_client.start_browser()
|
||||
if not browser_info:
|
||||
logger.error("启动 AdsPower 浏览器失败")
|
||||
return
|
||||
|
||||
# 通过 CDP 连接到浏览器
|
||||
browser = self.adspower_client.connect_browser(browser_info)
|
||||
if not browser:
|
||||
logger.error("连接浏览器失败")
|
||||
return
|
||||
|
||||
# 获取页面
|
||||
page = self.adspower_client.get_page(browser)
|
||||
if not page:
|
||||
logger.error("获取页面失败")
|
||||
return
|
||||
|
||||
# 执行广告点击操作
|
||||
automation = MIPAdAutomation(page)
|
||||
click_success, has_reply = automation.check_and_click_ad(url)
|
||||
|
||||
# 更新数据统计
|
||||
with self.lock:
|
||||
if click_success:
|
||||
self.data_manager.record_click(url, has_reply)
|
||||
logger.info(f"URL点击成功,获得回复: {has_reply}")
|
||||
else:
|
||||
logger.warning(f"URL点击失败: {url}")
|
||||
|
||||
# 随机延迟
|
||||
delay = random.randint(10, 30)
|
||||
time.sleep(delay)
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"处理URL异常: {str(e)}")
|
||||
|
||||
finally:
|
||||
# 停止浏览器(会自动清理 Playwright 资源)
|
||||
try:
|
||||
self.adspower_client.stop_browser()
|
||||
except Exception as e:
|
||||
logger.error(f"停止浏览器异常: {str(e)}")
|
||||
|
||||
|
||||
def get_statistics(self) -> Dict:
|
||||
"""
|
||||
获取统计数据
|
||||
|
||||
Returns:
|
||||
统计数据
|
||||
"""
|
||||
return self.data_manager.get_statistics()
|
||||
|
||||
def get_url_detail(self, url: str) -> Dict:
|
||||
"""
|
||||
获取URL详细信息
|
||||
|
||||
Args:
|
||||
url: URL
|
||||
|
||||
Returns:
|
||||
URL详细信息
|
||||
"""
|
||||
return self.data_manager.get_url_info(url)
|
||||
Reference in New Issue
Block a user