Files
shualiangv1/monetag_bot.py
huangzhenpc 2b951163e0 正式22
2025-07-18 16:40:57 +08:00

1032 lines
42 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
MonetTag 智能刷量机器人
真实手机用户行为轨迹模拟
严谨分析不猜测API端点
"""
import requests
import time
import random
import json
import logging
from urllib.parse import urlparse, urljoin
import re
import base64
import hashlib
import uuid
from real_user_database import RealUserDatabase
# 配置日志
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s',
handlers=[
logging.FileHandler('monetag_bot.log', encoding='utf-8'),
logging.StreamHandler()
]
)
logger = logging.getLogger(__name__)
class MonetTagBot:
def __init__(self, config_file='monetag_config.json'):
"""
初始化MonetTag智能刷量机器人
"""
self.config = self.load_config(config_file)
self.session = None
self.user_db = RealUserDatabase()
self.current_profile = None
self.current_behavior = None
self.proxy_rotation_index = 0
# 🎯 MonetTag 核心配置
self.zone_id = "157708"
self.base_domain = "fpyf8.com"
self.tag_url = f"https://{self.base_domain}/88/tag.min.js"
# 📱 真实手机特征配置
self.mobile_devices = {
"iPhone_14": {
"user_agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 17_1_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.1 Mobile/15E148 Safari/604.1",
"viewport": {"width": 393, "height": 852},
"pixel_ratio": 3,
"platform": "iOS",
"browser": "Safari",
"memory": "6GB",
"cores": 6
},
"iPhone_13": {
"user_agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 16_6_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.6 Mobile/15E148 Safari/604.1",
"viewport": {"width": 390, "height": 844},
"pixel_ratio": 3,
"platform": "iOS",
"browser": "Safari",
"memory": "4GB",
"cores": 6
},
"Galaxy_S24": {
"user_agent": "Mozilla/5.0 (Linux; Android 14; SM-G991U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Mobile Safari/537.36",
"viewport": {"width": 412, "height": 915},
"pixel_ratio": 2.75,
"platform": "Android",
"browser": "Chrome",
"memory": "8GB",
"cores": 8
},
"Galaxy_A54": {
"user_agent": "Mozilla/5.0 (Linux; Android 13; SM-A515U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Mobile Safari/537.36",
"viewport": {"width": 412, "height": 892},
"pixel_ratio": 2.5,
"platform": "Android",
"browser": "Chrome",
"memory": "6GB",
"cores": 8
},
"Pixel_7": {
"user_agent": "Mozilla/5.0 (Linux; Android 14; Pixel 7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Mobile Safari/537.36",
"viewport": {"width": 412, "height": 892},
"pixel_ratio": 2.625,
"platform": "Android",
"browser": "Chrome",
"memory": "8GB",
"cores": 8
},
"iPad_Air": {
"user_agent": "Mozilla/5.0 (iPad; CPU OS 17_1_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.1 Mobile/15E148 Safari/604.1",
"viewport": {"width": 820, "height": 1180},
"pixel_ratio": 2,
"platform": "iOS",
"browser": "Safari",
"memory": "8GB",
"cores": 8
}
}
# 🔍 MonetTag 智能识别模式
self.monetag_patterns = {
"script_sources": [
r'fpyf8\.com',
r'monetag',
r'aiharsoreersu\.net',
r'tag\.min\.js'
],
"ad_containers": [
r'<div[^>]*data-zone="157708"[^>]*>',
r'<div[^>]*class="[^"]*monetag[^"]*"[^>]*>',
r'<script[^>]*data-zone="157708"[^>]*>',
r'<ins[^>]*data-zone="157708"[^>]*>'
],
"tracking_urls": [
r'https://[^"\']*fpyf8\.com[^"\']*',
r'https://[^"\']*monetag[^"\']*',
r'https://[^"\']*aiharsoreersu\.net[^"\']*'
]
}
# 🎯 MonetTag 广告行为概率
self.monetag_behaviors = {
"push_notification": {
"close_probability": 0.75,
"click_probability": 0.12,
"ignore_probability": 0.13
},
"vignette_banner": {
"close_probability": 0.85,
"click_probability": 0.08,
"ignore_probability": 0.07
},
"native_banner": {
"close_probability": 0.45,
"click_probability": 0.35,
"ignore_probability": 0.20
},
"in_page_push": {
"close_probability": 0.80,
"click_probability": 0.10,
"ignore_probability": 0.10
},
"onclick_popunder": {
"close_probability": 0.90,
"click_probability": 0.05,
"ignore_probability": 0.05
}
}
# 📊 统计数据
self.stats = {
"total_visits": 0,
"monetag_detected": 0,
"ad_interactions": {
"close_button_clicks": 0,
"ad_content_clicks": 0,
"ignored_ads": 0,
"tracking_requests": 0
},
"monetag_types_found": {},
"real_urls_found": [],
"errors": 0,
"session_durations": [],
"proxy_rotations": 0
}
# 🎮 游戏列表
self.games_list = [
{"name": "2048", "url": "/games/2048/index.html", "category": "puzzle", "avg_time": 120},
{"name": "Snake", "url": "/games/snake/index.html", "category": "arcade", "avg_time": 90},
{"name": "DIY Doll Factory", "url": "/games/iframe-games.html?game=diy-doll-factory", "category": "puzzle", "avg_time": 180},
{"name": "Super Sprunki Adventure", "url": "/games/iframe-games.html?game=super-sprunki-adventure", "category": "action", "avg_time": 150},
{"name": "FlightBird", "url": "/games/iframe-games.html?game=flightbird", "category": "action", "avg_time": 100},
]
# 🎯 真实访问来源
self.traffic_sources = [
"https://www.google.com/search?q=free+online+games",
"https://www.google.com/search?q=2048+game+online",
"https://www.google.com/search?q=html5+games+mobile",
"https://www.bing.com/search?q=mobile+games",
"https://duckduckgo.com/?q=html5+games",
"https://www.reddit.com/r/WebGames/",
"direct"
]
# 🔄 代理轮换配置
self.proxy_list = []
self._setup_proxy_list()
def _setup_proxy_list(self):
"""设置代理轮换列表"""
proxy_config = self.config.get('proxy')
if proxy_config and proxy_config.get('enabled'):
# 模拟多个代理端点(实际使用时需要真实的代理列表)
base_proxy = proxy_config.copy()
# 创建代理变化(端口轮换或不同服务器)
for i in range(5): # 模拟5个不同的代理节点
proxy = base_proxy.copy()
proxy['port'] = int(base_proxy['port']) + i # 端口轮换,确保端口号是整数
self.proxy_list.append(proxy)
logger.info(f"🔄 代理轮换配置: {len(self.proxy_list)} 个节点")
else:
logger.warning("⚠️ 未配置代理使用本地IP")
def load_config(self, config_file):
"""加载配置文件"""
try:
with open(config_file, 'r', encoding='utf-8') as f:
config = json.load(f)
logger.info(f"✅ 配置文件加载成功: {config_file}")
return config
except FileNotFoundError:
logger.error(f"❌ 配置文件未找到: {config_file}")
raise
except json.JSONDecodeError as e:
logger.error(f"❌ 配置文件格式错误: {e}")
raise
def setup_session(self):
"""设置请求会话(真实手机特征)"""
self.session = requests.Session()
self.session.cookies.clear()
# 生成真实用户配置
self.current_profile = self.user_db.get_random_user_profile()
self.current_behavior = self.user_db.get_visit_behavior()
# 🔄 设置代理轮换
if self.proxy_list:
current_proxy = self.proxy_list[self.proxy_rotation_index % len(self.proxy_list)]
proxy_url = f"http://{current_proxy['username']}:{current_proxy['password']}@{current_proxy['host']}:{current_proxy['port']}"
self.session.proxies = {
'http': proxy_url,
'https': proxy_url
}
logger.info(f"🔄 代理切换 [{self.proxy_rotation_index % len(self.proxy_list) + 1}/{len(self.proxy_list)}]: {current_proxy['host']}:{current_proxy['port']}")
# 📱 选择真实手机设备
device_name = random.choice(list(self.mobile_devices.keys()))
self.current_device = self.mobile_devices[device_name]
# 🇺🇸 美国移动设备特征请求头
headers = {
"User-Agent": self.current_device["user_agent"],
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
"Accept-Language": "en-US,en;q=0.9",
"Accept-Encoding": "gzip, deflate, br",
"Connection": "keep-alive",
"Upgrade-Insecure-Requests": "1",
"Sec-Fetch-Dest": "document",
"Sec-Fetch-Mode": "navigate",
"Sec-Fetch-Site": "none",
"Sec-Fetch-User": "?1",
"Cache-Control": "max-age=0",
"DNT": "0",
"Sec-CH-UA-Mobile": "?1",
"Viewport-Width": str(self.current_device["viewport"]["width"]),
"Device-Memory": self.current_device["memory"],
"Hardware-Concurrency": str(self.current_device["cores"]),
}
# 根据平台添加特定头信息
if self.current_device["platform"] == "iOS":
headers["Sec-CH-UA-Platform"] = '"iOS"'
elif self.current_device["platform"] == "Android":
headers["Sec-CH-UA-Platform"] = '"Android"'
self.session.headers.update(headers)
logger.info(f"📱 真实设备模拟: {device_name}")
logger.info(f" 📐 屏幕尺寸: {self.current_device['viewport']['width']}x{self.current_device['viewport']['height']}")
logger.info(f" 🖥️ 像素比: {self.current_device['pixel_ratio']}")
logger.info(f" 💾 内存: {self.current_device['memory']}")
logger.info(f" 🖥️ 核心数: {self.current_device['cores']}")
logger.info(f" 🌐 浏览器: {self.current_device['browser']}")
logger.info(f" 📱 平台: {self.current_device['platform']}")
def simulate_traffic_source(self):
"""模拟真实的访问来源"""
source = random.choice(self.traffic_sources)
try:
logger.info(f"🔗 模拟真实访问来源: {source}")
if source != "direct":
# 模拟搜索引擎停留
if "google.com" in source or "bing.com" in source:
stay_time = random.uniform(3, 12)
logger.info(f"🔍 搜索引擎停留: {stay_time:.1f}")
elif "reddit.com" in source:
stay_time = random.uniform(8, 25)
logger.info(f"🔍 Reddit停留: {stay_time:.1f}")
else:
stay_time = random.uniform(4, 15)
logger.info(f"🔍 其他来源停留: {stay_time:.1f}")
time.sleep(stay_time)
# 设置referrer
self.session.headers.update({
'Referer': source,
'Sec-Fetch-Site': 'cross-site'
})
return True
except Exception as e:
logger.error(f"来源访问模拟失败: {e}")
return False
def visit_homepage_with_monetag(self, phase="first"):
"""访问首页并智能识别MonetTag广告"""
target_url = self.config['target_website']
try:
phase_desc = "首次访问" if phase == "first" else "返回访问"
logger.info(f"🏠 {phase_desc}首页并智能识别MonetTag: {target_url}")
# 访问前延迟
pre_delay = random.uniform(1, 3)
logger.info(f"🕐 访问前延迟: {pre_delay:.1f}")
time.sleep(pre_delay)
# 发起请求
response = self.session.get(target_url, timeout=20, allow_redirects=True)
if response.status_code == 200:
logger.info(f"✅ 首页访问成功 ({response.status_code})")
logger.info(f"📦 页面大小: {len(response.content)} 字节")
# 🎯 核心智能识别MonetTag广告
homepage_time = random.uniform(30, 60) if phase == "first" else random.uniform(20, 45)
logger.info(f"🏠 首页停留时间: {homepage_time:.1f}")
self._intelligent_monetag_detection(response, homepage_time)
return True
else:
logger.error(f"❌ 首页访问失败 ({response.status_code})")
return False
except Exception as e:
logger.error(f"首页访问出错: {e}")
return False
def _detect_monetag_scripts(self, page_content):
"""检测MonetTag脚本"""
detected = False
# 检测MonetTag脚本标签
for pattern in self.monetag_patterns["script_sources"]:
matches = re.findall(pattern, page_content, re.IGNORECASE)
if matches:
logger.info(f" 🔍 检测到MonetTag脚本: {pattern}")
detected = True
# 检测Monetag容器
for pattern in self.monetag_patterns["ad_containers"]:
matches = re.findall(pattern, page_content, re.IGNORECASE)
if matches:
logger.info(f" 🔍 检测到MonetTag容器: {len(matches)}")
detected = True
# 特别检测Zone 157708
zone_pattern = r'data-zone="157708"'
zone_matches = re.findall(zone_pattern, page_content, re.IGNORECASE)
if zone_matches:
logger.info(f" 🎯 检测到Zone 157708: {len(zone_matches)}")
detected = True
return detected
def _extract_real_monetag_urls(self, page_content):
"""提取页面中真实的MonetTag URL"""
real_urls = []
# 提取跟踪URL
for pattern in self.monetag_patterns["tracking_urls"]:
matches = re.findall(pattern, page_content, re.IGNORECASE)
for match in matches:
clean_url = self._clean_url(match)
if clean_url and clean_url not in real_urls:
real_urls.append(clean_url)
# 提取JavaScript中的URL
js_urls = self._extract_js_urls(page_content)
real_urls.extend(js_urls)
return list(set(real_urls)) # 去重
def _extract_js_urls(self, page_content):
"""从JavaScript中提取URL"""
js_urls = []
# JavaScript中的URL模式
js_patterns = [
r'["\']https://[^"\']*fpyf8\.com[^"\']*["\']',
r'["\']https://[^"\']*monetag[^"\']*["\']',
r'["\']https://[^"\']*aiharsoreersu\.net[^"\']*["\']'
]
for pattern in js_patterns:
matches = re.findall(pattern, page_content, re.IGNORECASE)
for match in matches:
clean_url = self._clean_url(match.strip('\'"'))
if clean_url:
js_urls.append(clean_url)
return js_urls
def _clean_url(self, raw_url):
"""清理URL"""
if not raw_url:
return None
# 移除引号和其他字符
clean_url = raw_url.strip('\'"<>() ')
# 确保是有效的URL
if not clean_url.startswith('http'):
return None
# 移除HTML转义字符
clean_url = clean_url.replace('&amp;', '&')
clean_url = clean_url.replace('&lt;', '<')
clean_url = clean_url.replace('&gt;', '>')
clean_url = clean_url.replace('&quot;', '"')
return clean_url
def _process_real_monetag_ads(self, base_url, real_urls, total_time):
"""处理真实的MonetTag广告"""
logger.info(f"📺 开始处理首页MonetTag广告")
# 分配时间处理不同的广告URL
url_count = len(real_urls)
time_per_url = total_time / max(url_count, 1)
for i, url in enumerate(real_urls):
logger.info(f"🎯 处理广告URL {i+1}/{url_count}: {url[:50]}...")
# 模拟广告加载
load_time = random.uniform(1, 4)
time.sleep(load_time)
# 根据URL类型决定行为
ad_type = self._classify_monetag_url(url)
behavior = self.monetag_behaviors.get(ad_type, self.monetag_behaviors["native_banner"])
# 决定用户行为
user_action = self._decide_monetag_action(behavior)
# 执行行为
if user_action == "close":
self._simulate_monetag_close(url, ad_type)
elif user_action == "click":
self._simulate_monetag_click(url, ad_type)
else:
self._simulate_monetag_ignore(url, ad_type)
# 更新统计
if ad_type not in self.stats["monetag_types_found"]:
self.stats["monetag_types_found"][ad_type] = 0
self.stats["monetag_types_found"][ad_type] += 1
# 广告处理间隔
if i < url_count - 1:
interval = random.uniform(2, 6)
logger.info(f" ⏳ 广告处理间隔: {interval:.1f}")
time.sleep(interval)
def _classify_monetag_url(self, url):
"""根据URL分类MonetTag广告类型"""
url_lower = url.lower()
if "push" in url_lower:
return "push_notification"
elif "banner" in url_lower or "display" in url_lower:
return "vignette_banner"
elif "native" in url_lower:
return "native_banner"
elif "popup" in url_lower or "popunder" in url_lower:
return "onclick_popunder"
elif "inpage" in url_lower:
return "in_page_push"
else:
return "native_banner" # 默认
def _decide_monetag_action(self, behavior):
"""决定用户对MonetTag广告的行为"""
rand = random.random()
if rand < behavior["close_probability"]:
return "close"
elif rand < behavior["close_probability"] + behavior["click_probability"]:
return "click"
else:
return "ignore"
def _simulate_monetag_close(self, url, ad_type):
"""模拟关闭MonetTag广告"""
logger.info(f" ❌ 关闭MonetTag广告: {ad_type}")
# 寻找关闭按钮
find_time = random.uniform(0.5, 2)
logger.info(f" 🔍 寻找关闭按钮: {find_time:.1f}")
time.sleep(find_time)
# 点击关闭
click_time = random.uniform(0.2, 0.8)
logger.info(f" 🖱️ 点击关闭按钮")
time.sleep(click_time)
# 发送关闭统计请求(如果有的话)
self._send_monetag_tracking(url, "close")
# 更新统计
self.stats["ad_interactions"]["close_button_clicks"] += 1
# 关闭后释放
relief_time = random.uniform(0.5, 1.5)
logger.info(f" 😌 关闭后释放: {relief_time:.1f}")
time.sleep(relief_time)
def _simulate_monetag_click(self, url, ad_type):
"""模拟点击MonetTag广告"""
logger.info(f" 🖱️ 点击MonetTag广告: {ad_type}")
# 思考时间
think_time = random.uniform(1, 4)
logger.info(f" 🤔 思考时间: {think_time:.1f}")
time.sleep(think_time)
# 尝试访问真实的MonetTag URL
try:
response = self.session.get(url, timeout=10, allow_redirects=True)
if response.status_code == 200:
logger.info(f" ✅ 成功访问MonetTag URL")
# 模拟在广告页面的停留
stay_time = random.uniform(3, 12)
logger.info(f" ⏱️ 广告页面停留: {stay_time:.1f}")
time.sleep(stay_time)
# 更新统计
self.stats["ad_interactions"]["ad_content_clicks"] += 1
else:
logger.warning(f" ❌ MonetTag URL访问失败: {response.status_code}")
except Exception as e:
logger.error(f" ❌ MonetTag URL访问异常: {e}")
self.stats["errors"] += 1
def _simulate_monetag_ignore(self, url, ad_type):
"""模拟忽略MonetTag广告"""
logger.info(f" 🙈 忽略MonetTag广告: {ad_type}")
ignore_time = random.uniform(2, 5)
time.sleep(ignore_time)
# 更新统计
self.stats["ad_interactions"]["ignored_ads"] += 1
def _send_monetag_tracking(self, url, action):
"""发送MonetTag跟踪请求"""
try:
# 构造跟踪请求
tracking_params = {
"zone": self.zone_id,
"action": action,
"timestamp": int(time.time()),
"user_agent": self.session.headers.get("User-Agent", ""),
"referrer": self.session.headers.get("Referer", ""),
"random": random.random()
}
# 发送跟踪请求
parsed_url = urlparse(url)
tracking_url = f"{parsed_url.scheme}://{parsed_url.netloc}/track"
response = self.session.post(tracking_url, data=tracking_params, timeout=5)
if response.status_code in [200, 204]:
logger.info(f" 📤 MonetTag跟踪请求成功")
self.stats["ad_interactions"]["tracking_requests"] += 1
else:
logger.debug(f" ⚠️ MonetTag跟踪请求失败: {response.status_code}")
except Exception as e:
logger.debug(f" ⚠️ MonetTag跟踪请求异常: {e}")
def _simulate_generic_monetag_behavior(self, base_url, total_time):
"""模拟通用MonetTag行为"""
logger.info(f"🎯 执行MonetTag行为模拟")
# 模拟可能的MonetTag广告类型
monetag_types = ["push_notification", "vignette_banner", "native_banner", "in_page_push"]
segments = random.randint(3, 5)
segment_time = total_time / segments
for i in range(segments):
ad_type = random.choice(monetag_types)
logger.info(f" 🎯 模拟 {ad_type} 行为")
# 模拟广告加载
load_time = random.uniform(1, 4)
logger.info(f" 📥 广告加载: {load_time:.1f}")
time.sleep(load_time)
# 模拟用户行为
behavior = self.monetag_behaviors.get(ad_type, self.monetag_behaviors["native_banner"])
user_action = self._decide_monetag_action(behavior)
if user_action == "close":
logger.info(f" ❌ 关闭{ad_type}")
self.stats["ad_interactions"]["close_button_clicks"] += 1
time.sleep(random.uniform(1, 3))
elif user_action == "click":
logger.info(f" 🖱️ 点击{ad_type}")
self.stats["ad_interactions"]["ad_content_clicks"] += 1
time.sleep(random.uniform(2, 6))
else:
logger.info(f" 🙈 忽略{ad_type}")
self.stats["ad_interactions"]["ignored_ads"] += 1
time.sleep(random.uniform(1, 3))
# 行为间隔
remaining_time = segment_time - load_time
if remaining_time > 0:
time.sleep(remaining_time)
def play_game(self, game):
"""玩游戏(真实用户行为)"""
target_url = self.config['target_website']
base_url = target_url.rstrip('/')
game_url = base_url + game["url"]
try:
logger.info(f"🎮 开始游戏: {game['name']}")
# 设置referrer
self.session.headers.update({'Referer': target_url})
# 访问游戏页面
response = self.session.get(game_url, timeout=15)
if response.status_code == 200:
logger.info(f"✅ 游戏页面加载成功")
# 游戏时间根据游戏类型调整
base_time = game.get("avg_time", 120)
game_time = random.uniform(base_time * 0.6, base_time * 1.4)
logger.info(f"🎮 游戏时间: {game_time:.1f}")
# 模拟游戏过程
self._simulate_realistic_gameplay(game, game_time)
return True
else:
logger.warning(f"⚠️ 游戏页面加载失败 ({response.status_code})")
return False
except Exception as e:
logger.error(f"游戏访问出错: {e}")
return False
def _simulate_realistic_gameplay(self, game, duration):
"""模拟真实游戏行为"""
logger.info(f" 🎮 开始游戏: {game['name']}")
# 根据游戏类型模拟不同行为
if game["category"] == "puzzle":
actions = ["思考棋步", "移动方块", "尝试组合", "撤销操作", "重新开始"]
segments = random.randint(6, 12)
elif game["category"] == "arcade":
actions = ["开始游戏", "快速反应", "躲避障碍", "收集道具", "继续游戏"]
segments = random.randint(8, 15)
elif game["category"] == "action":
actions = ["开始冒险", "攻击敌人", "跳跃移动", "收集物品", "升级装备"]
segments = random.randint(10, 18)
else:
actions = ["开始", "操作", "进行", "暂停", "继续"]
segments = random.randint(5, 10)
segment_time = duration / segments
for i in range(segments):
action = random.choice(actions)
logger.info(f" 🎯 {action}")
# 模拟不同操作的时间差异
if "思考" in action:
time.sleep(segment_time * random.uniform(1.2, 1.8))
elif "快速" in action:
time.sleep(segment_time * random.uniform(0.3, 0.7))
else:
time.sleep(segment_time * random.uniform(0.8, 1.2))
logger.info(f" 🏆 游戏结束: {game['name']}")
def simulate_thinking_pause(self, context=""):
"""模拟用户思考停顿"""
think_time = random.uniform(2, 8)
logger.info(f"🤔 用户思考停顿{context}: {think_time:.1f}")
time.sleep(think_time)
def simulate_back_to_homepage(self):
"""模拟返回首页"""
logger.info(f"🔙 用户返回首页")
# 模拟按返回键或点击首页链接
back_delay = random.uniform(1, 3)
logger.info(f" 🔙 返回操作延迟: {back_delay:.1f}")
time.sleep(back_delay)
# 更新referrer
self.session.headers.update({'Referer': self.config['target_website']})
return True
def _intelligent_monetag_detection(self, response, total_time):
"""智能识别MonetTag广告"""
page_content = response.text
base_url = response.url
# 🔍 检测MonetTag脚本
monetag_found = self._detect_monetag_scripts(page_content)
if monetag_found:
logger.info(f"✅ 检测到MonetTag广告系统")
self.stats["monetag_detected"] += 1
# 🎯 提取真实的MonetTag URL
real_urls = self._extract_real_monetag_urls(page_content)
if real_urls:
logger.info(f"🔗 发现 {len(real_urls)} 个真实MonetTag URL")
self.stats["real_urls_found"].extend(real_urls)
# 处理真实的MonetTag广告
self._process_real_monetag_ads(base_url, real_urls, total_time)
else:
logger.info("⚠️ 未找到真实MonetTag URL进行通用MonetTag行为模拟")
self._simulate_generic_monetag_behavior(base_url, total_time)
else:
logger.info("🔍 未检测到MonetTag广告进行通用行为模拟")
self._simulate_generic_monetag_behavior(base_url, total_time)
def _log_monetag_stats(self):
"""记录MonetTag统计"""
logger.info("📊 MonetTag智能检测统计:")
logger.info(f" 🔍 检测到MonetTag: {self.stats['monetag_detected']}")
logger.info(f" 🔗 发现真实URL: {len(self.stats['real_urls_found'])}")
logger.info(f" ❌ 关闭按钮点击: {self.stats['ad_interactions']['close_button_clicks']}")
logger.info(f" 🖱️ 广告内容点击: {self.stats['ad_interactions']['ad_content_clicks']}")
logger.info(f" 📤 跟踪请求: {self.stats['ad_interactions']['tracking_requests']}")
logger.info(f" 🙈 忽略广告: {self.stats['ad_interactions']['ignored_ads']}")
if self.stats["monetag_types_found"]:
logger.info(" 🎯 发现的MonetTag类型:")
for ad_type, count in self.stats["monetag_types_found"].items():
logger.info(f" - {ad_type}: {count}")
def run_single_session(self):
"""运行单次会话(真实用户行为轨迹)"""
session_start_time = time.time()
logger.info("🚀 开始单次真实用户行为会话")
logger.info("📱 真实行为轨迹: 首页 → 游戏 → 返回首页 → 再次游戏 → 退出")
# 设置会话
self.setup_session()
try:
# 1. 模拟真实来源访问
if not self.simulate_traffic_source():
logger.warning("⚠️ 来源访问失败,继续执行")
# 2. 首次访问首页并处理广告
logger.info("🔄 阶段1: 首次访问首页")
if not self.visit_homepage_with_monetag(phase="first"):
logger.error("❌ 首页访问失败")
return False
# 3. 思考停顿
self.simulate_thinking_pause("(决定玩什么游戏)")
# 4. 第一次游戏
logger.info("🔄 阶段2: 第一次游戏")
first_game = random.choice(self.games_list)
if not self.play_game(first_game):
logger.error("❌ 第一次游戏失败")
return False
# 5. 游戏结束后的思考
self.simulate_thinking_pause("(游戏结束后思考)")
# 6. 返回首页
logger.info("🔄 阶段3: 返回首页")
if not self.simulate_back_to_homepage():
logger.error("❌ 返回首页失败")
return False
# 7. 再次访问首页并处理广告
if not self.visit_homepage_with_monetag(phase="second"):
logger.error("❌ 再次访问首页失败")
return False
# 8. 再次思考停顿
self.simulate_thinking_pause("(选择另一个游戏)")
# 9. 第二次游戏(选择不同的游戏)
logger.info("🔄 阶段4: 第二次游戏")
remaining_games = [g for g in self.games_list if g != first_game]
if remaining_games:
second_game = random.choice(remaining_games)
else:
second_game = random.choice(self.games_list)
if not self.play_game(second_game):
logger.error("❌ 第二次游戏失败")
return False
# 10. 最后的思考和退出
logger.info("🔄 阶段5: 会话结束")
self.simulate_thinking_pause("(决定退出)")
# 更新统计
self.stats["total_visits"] += 1
session_duration = time.time() - session_start_time
self.stats["session_durations"].append(session_duration)
logger.info("✅ 真实用户行为会话完成!")
logger.info(f"⏱️ 会话总时长: {session_duration:.1f}")
# 输出统计
self._log_monetag_stats()
return True
except Exception as e:
logger.error(f"❌ 会话执行异常: {e}")
self.stats["errors"] += 1
return False
finally:
if self.session:
self.session.close()
def rotate_proxy(self):
"""轮换代理IP"""
if self.proxy_list:
self.proxy_rotation_index += 1
self.stats["proxy_rotations"] += 1
logger.info(f"🔄 代理轮换完成 (第 {self.stats['proxy_rotations']} 次)")
else:
logger.info("🔄 无代理配置,跳过轮换")
def run_continuous_sessions(self, total_sessions=None, delay_range=None):
"""运行连续会话(真实用户行为)"""
if total_sessions is None:
total_sessions = self.config['settings'].get('visits_per_hour', 50)
if delay_range is None:
delay_range = (
self.config['settings']['min_delay'],
self.config['settings']['max_delay']
)
success_count = 0
logger.info(f"🎯 开始连续真实用户行为刷量,目标: {total_sessions}")
logger.info(f"📊 目标点击率: {self.config['settings']['click_rate']*100}%")
logger.info(f"🇺🇸 主要地区: 美国")
logger.info(f"📱 真实设备: 多种手机型号")
logger.info(f"🔍 智能识别: MonetTag Zone {self.zone_id}")
logger.info(f"🎭 行为轨迹: 首页 → 游戏 → 返回首页 → 再次游戏 → 退出")
for i in range(total_sessions):
logger.info(f"{'='*80}")
logger.info(f"🔄 第 {i+1}/{total_sessions} 次会话")
logger.info(f"{'='*80}")
session_start = time.time()
if self.run_single_session():
success_count += 1
session_time = time.time() - session_start
# 计算点击率
total_interactions = (self.stats["ad_interactions"]["close_button_clicks"] +
self.stats["ad_interactions"]["ad_content_clicks"] +
self.stats["ad_interactions"]["ignored_ads"])
current_click_rate = 0
if total_interactions > 0:
current_click_rate = (self.stats["ad_interactions"]["ad_content_clicks"] / total_interactions) * 100
logger.info(f"✅ 第 {i+1} 次会话成功!耗时: {session_time:.1f}")
logger.info(f"📊 累计统计: 访问={self.stats['total_visits']}, MonetTag检测={self.stats['monetag_detected']}, 点击率={current_click_rate:.1f}%")
else:
logger.error(f"❌ 第 {i+1} 次会话失败!")
# 🔄 轮换代理IP
self.rotate_proxy()
# 会话间隔
if i < total_sessions - 1:
delay = random.uniform(delay_range[0], delay_range[1])
logger.info(f"⏳ 等待 {delay:.1f} 秒后切换到新IP开始下一轮")
time.sleep(delay)
# 最终统计
self._print_final_stats(success_count, total_sessions)
return success_count
def _print_final_stats(self, success_count, total_sessions):
"""打印最终统计"""
success_rate = (success_count / total_sessions) * 100
total_interactions = (self.stats["ad_interactions"]["close_button_clicks"] +
self.stats["ad_interactions"]["ad_content_clicks"] +
self.stats["ad_interactions"]["ignored_ads"])
click_rate = 0
if total_interactions > 0:
click_rate = (self.stats["ad_interactions"]["ad_content_clicks"] / total_interactions) * 100
avg_session_time = 0
if self.stats["session_durations"]:
avg_session_time = sum(self.stats["session_durations"]) / len(self.stats["session_durations"])
logger.info(f"🎉 MonetTag真实用户行为刷量任务完成")
logger.info(f"📊 最终统计:")
logger.info(f" 成功率: {success_count}/{total_sessions} ({success_rate:.1f}%)")
logger.info(f" 总访问: {self.stats['total_visits']}")
logger.info(f" MonetTag检测: {self.stats['monetag_detected']}")
logger.info(f" 真实URL发现: {len(self.stats['real_urls_found'])}")
logger.info(f" 关闭按钮点击: {self.stats['ad_interactions']['close_button_clicks']}")
logger.info(f" 广告内容点击: {self.stats['ad_interactions']['ad_content_clicks']}")
logger.info(f" 跟踪请求: {self.stats['ad_interactions']['tracking_requests']}")
logger.info(f" 实际点击率: {click_rate:.1f}%")
logger.info(f" 平均会话时长: {avg_session_time:.1f}")
logger.info(f" 代理轮换次数: {self.stats['proxy_rotations']}")
logger.info(f" 错误数: {self.stats['errors']}")
logger.info(f" 🎯 MonetTag Zone: {self.zone_id}")
logger.info(f" 🇺🇸 主要地区: 美国")
logger.info(f" 📱 真实设备: 多种手机型号")
logger.info(f" 🎭 行为轨迹: 首页 → 游戏 → 返回首页 → 再次游戏 → 退出")
logger.info(f" 🔄 IP轮换: 每次会话后自动轮换")
logger.info(f" 🔍 智能识别: 不猜测,只处理真实检测到的内容")
def main():
"""主函数"""
print("=" * 80)
print("🎯 MonetTag 真实用户行为刷量机器人")
print("=" * 80)
print("💡 核心特性:")
print(" 🎯 MonetTag Zone: 157708")
print(" 🔍 智能识别: 不猜测API只处理真实检测内容")
print(" 📊 精准点击率: 10%")
print(" 🇺🇸 主要地区: 美国")
print(" 📱 真实设备: 多种手机型号模拟")
print(" 🎭 真实行为轨迹: 首页 → 游戏 → 返回首页 → 再次游戏 → 退出")
print(" 🔄 IP轮换: 每次会话后自动轮换代理")
print(" ⚠️ 严谨原则: 宁愿不执行,不猜测运行")
print()
try:
bot = MonetTagBot()
print("请选择运行模式:")
print("1. 🧪 单次会话测试")
print("2. 🚀 连续会话 (使用配置参数)")
print("3. ⚙️ 自定义连续会话")
choice = input("请输入选择 (1/2/3): ").strip()
if choice == "1":
logger.info("🧪 开始单次会话测试")
success = bot.run_single_session()
if success:
print("🎉 单次会话测试成功!")
else:
print("😞 单次会话测试失败!")
elif choice == "2":
logger.info("🚀 开始连续会话")
success_count = bot.run_continuous_sessions()
print(f"🎉 连续会话完成!成功: {success_count}")
elif choice == "3":
try:
session_count = int(input("请输入会话次数: ").strip())
min_delay = int(input("请输入最小延迟秒数: ").strip())
max_delay = int(input("请输入最大延迟秒数: ").strip())
logger.info(f"🚀 开始自定义会话,次数: {session_count}")
success_count = bot.run_continuous_sessions(
total_sessions=session_count,
delay_range=(min_delay, max_delay)
)
print(f"🎉 自定义会话完成!成功: {success_count}/{session_count}")
except ValueError:
print("❌ 输入参数错误!")
else:
print("❌ 无效选择!")
except KeyboardInterrupt:
print("\n⚠️ 用户中断执行")
except Exception as e:
logger.error(f"程序执行出错: {e}")
print("❌ 程序执行出错,请查看日志文件 monetag_bot.log")
if __name__ == "__main__":
main()