随机代理IP访问脚本
- 前言
-
- requests方式
- [requests + Playwright 方式](#requests + Playwright 方式)
前言
AI真是好东西或者说好助手,以前写脚本还得查需要用哪些模块,哪些模块能实现某个功能,然后还得现学对应模块的函数和用法等,接着编辑,测试,调整,继续优化等。如果过去没有积累现成的脚本,用现成的脚本改的话,需要很长的时间重复造轮子。并且运行正常后长时间不管不看,过去写好的某个脚本,对于它的具体写法和逻辑还得回忆和再分析,不加注释更完蛋。
而现在当我们需要某些功能的时候去告知AI,它可以提供示例甚至半成品,乃至成品代码,只需要微调或者再次告诉它自己的想法即可,甚至连过去学python或者某些语法到皮毛的程度,现在都不需要你去掌握,可能只需要调整参数Flase or True,越短越简单,越容易实现,越复杂的(只要不超过上下文或者文件数过多,结构够杂乱这种)实现的比一般人好。当然要想学某些东西,可以加快理解,但是大多数情况,当人们用习惯用了某种工具未必还会在意内在的逻辑。
当然在过去几年一些AI也一直支持代码方面的能力,但我想说的是到了今天显然的更加的成熟了,需要工作人员去做的越来越少。当然对于一些中大型的代码项目的开发(不是脚本)来说,虽然仍然存在上下文导致的遗忘或者幻觉等问题,但各个专业方面的AI明显的在爆炸式的进步,就代码方面说不定哪天机器人,如果让它自我更新,说不定就做到自我优化代码和自己生产自己了,像是某科幻电影和小说,给机器人授权或者下指令让它们自我生产和优化代码,结果人类没了,机器还不断生产,飞向宇宙了。
扯的有点多,写这些的目的是有点感想与光挂代码不好看和莫名其妙。
没敏感内容就分享了,功能:循环代理池中的IP随机轮询测试网址。
requests方式
bash
import requests
import time
import re
from fake_useragent import UserAgent
import random
import sys, os
class Tee:
def __init__(self, *files):
self.files = files
def write(self, text):
for f in self.files:
f.write(text)
f.flush()
def flush(self):
for f in self.files:
f.flush()
# 明确把日志写在脚本旁边
script_dir = os.path.dirname(os.path.abspath(__file__))
log_path = os.path.join(script_dir, 'proxy_visit.log')
try:
log_file = open(log_path, 'a', encoding='utf-8')
sys.stdout = Tee(sys.stdout, log_file)
print(f"📝 日志文件已创建: {log_path}")
except Exception as e:
print(f"❌ 无法创建日志文件: {e}")
# ==================== 配置区 ====================
# ===============================================
# 循环控制参数
# ===============================================
LOOP_ENABLED = True # 是否启用无限循环
LOOP_INTERVAL = 5 # 每次循环间隔(秒)
MAX_LOOP_COUNT = None # 最大循环次数,None表示无限循环
# ===============================================
# 代理参数
TIMEOUT = 10 # 请求超时时间(秒)
MAX_RETRIES = 3 # 最大重试次数(使用代理时)
USE_FAKE_UA = True # 是否启用随机 User-Agent(需安装 fake-useragent)
# ===============================================
TEST_URL = "http://myip.ipip.net" # 代理验证测试地址
# ===============================================
# 替换为你要访问的目标网址
TARGET_URLS = [
"http://123.com",
"https://1234.com",
"http://123.top"
]
# 原始代理列表(每行一个 IP:端口)
raw_proxies = """
121.31.233.124:1111
121.31.233.123:11111
121.31.233.122:12222
"""
# ===============================================
# 初始化 User-Agent 生成器
ua = UserAgent() if USE_FAKE_UA else None
PROXY_LIST = []
PROXY_DETAILS = {}
DIRECT_IP = "未知"
def init_direct_ip():
"""仅运行一次,获取本机直连出口IP"""
global DIRECT_IP
_, _, ip = validate_proxy(None) # 不传代理,测试本机出口
DIRECT_IP = ip or "未知"
# 转换为标准 HTTP 代理格式
def convert_to_http_proxies(raw_text):
# 按行分割,去除空行和首尾空格
lines = [line.strip() for line in raw_text.strip().split('\n') if line.strip()]
# 为每行添加 http:// 前缀
return [f"http://{line}" for line in lines]
def make_request(url, proxy=None, timeout=TIMEOUT):
"""
发起单次 HTTP 请求,支持代理和直连
返回: (success: bool, used_proxy: str, elapsed_ms: int, response_text: str)
"""
headers = {"User-Agent": ua.random} if ua else {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"}
start = time.time()
try:
proxies = {"http": proxy, "https": proxy} if proxy else None
resp = requests.get(url, proxies=proxies, headers=headers,
timeout=timeout, allow_redirects=True)
elapsed = round((time.time() - start) * 1000, 2)
if resp.status_code == 200:
preview = resp.text[:200] + "..." if len(resp.text) > 200 else resp.text
return True, proxy or "直连", elapsed, preview
return False, proxy or "直连", elapsed, f"HTTP {resp.status_code}"
except requests.exceptions.Timeout:
elapsed = round((time.time() - start) * 1000, 2)
return False, proxy or "直连", elapsed, "请求超时"
except requests.exceptions.ConnectionError:
elapsed = round((time.time() - start) * 1000, 2)
return False, proxy or "直连", elapsed, "连接失败"
except Exception as e:
elapsed = round((time.time() - start) * 1000, 2)
return False, proxy or "直连", elapsed, str(e)
def validate_proxy(proxy):
"""
验证代理是否有效且真正工作
返回: (is_valid: bool, response_time: float, actual_ip: str or None)
"""
try:
success, _, response_time, response_text = make_request(TEST_URL, proxy, timeout=8)
if not success:
return False, response_time, None
# 用正则匹配 "当前 IP:x.x.x.x" 中的IP
match = re.search(r'当前\s*IP\s*[::]\s*(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})', response_text)
if match:
actual_ip = match.group(1)
else:
actual_ip = None
return True, response_time, actual_ip
except Exception:
return False, 0, None
def refresh_proxy_pool():
"""
完整验证代理池,返回有效代理列表和详细信息
返回: (valid_proxies: list, proxy_details: dict)
"""
global PROXY_LIST, PROXY_DETAILS
all_proxies = convert_to_http_proxies(raw_proxies)
valid = []
details = {}
print("🔄 开始验证代理有效性...")
print(f"共发现 {len(all_proxies)} 个代理需要验证")
print("-" * 60)
for proxy in all_proxies:
ok, rt, ip = validate_proxy(proxy)
details[proxy] = {"valid": ok, "response_time": rt, "actual_ip": ip}
if ok:
valid.append(proxy)
print(f" ✅ {proxy}")
print(f" 响应时间: {rt}ms | 实际IP: {ip}")
else:
print(f" ❌ {proxy} - 无效")
PROXY_LIST = valid
PROXY_DETAILS = details
total = len(all_proxies)
vcount = len(valid)
rate = (vcount / total * 100) if total > 0 else 0
print("-" * 60)
print(f"📊 代理池更新完成 | 原始: {total} | 有效: {vcount} | 有效率: {rate:.1f}%")
def get_random_proxy():
"""从代理列表中随机返回一个代理,若列表为空则返回 None"""
return random.choice(PROXY_LIST) if PROXY_LIST else None
def visit_urls_with_proxy_pool():
"""单次循环:使用代理池访问所有目标网址"""
print("🚀 开始使用代理池访问目标网址...\n")
results = []
for url in TARGET_URLS:
success = False
used_proxy = "直连"
elapsed_ms = 0
response_preview = ""
real_ip = "未知"
# 尝试最多 MAX_RETRIES 次使用不同代理
for attempt in range(MAX_RETRIES):
proxy = get_random_proxy()
if not proxy:
print(f"⚠️ 代理列表为空,跳过代理尝试,直接直连 {url}")
break
proxy_ip = PROXY_DETAILS.get(proxy, {}).get("actual_ip", "未验证")
print(f"🔁 第 {attempt + 1} 次尝试,代理: {proxy} -> 出口IP: {proxy_ip})-> 访问地址: {url}")
success, used_proxy, elapsed_ms, response_preview = make_request(url, proxy)
if success:
real_ip = PROXY_DETAILS.get(proxy, {}).get("actual_ip", "未知")
print(f"✅ 成功!耗时 {elapsed_ms}ms 出口IP: {real_ip}\n")
break
else:
print(f"❌ 失败: {response_preview}\n")
# 若所有代理尝试均失败,则降级为直连,只要尚未成功就尝试直连
if not success:
print(f"📉 所有代理尝试失败,降级为直连访问 {url}")
success, used_proxy, elapsed_ms, response_preview = make_request(url)
if success:
real_ip = DIRECT_IP # 直连出口IP
print(f"✅ 直连成功!耗时 {elapsed_ms}ms 出口IP: {real_ip}")
else:
print(f"❌ 直连也失败: {response_preview}\n")
# 记录结果
status = "成功" if success else "失败"
results.append({
"目标URL": url,
"使用的代理": used_proxy,
"请求状态": status,
"耗时(ms)": elapsed_ms,
"出口IP": real_ip
})
print(f"📌 最终结果: {url} | {status} | {elapsed_ms}ms | 代理: {used_proxy} | 出口IP: {real_ip}\n" + "-"*60)
# 输出汇总表格
print("\n📊 本次循环访问结果汇总:")
print(f"{'目标URL':<30} {'使用的代理':<20} {'请求状态':<8} {'耗时(ms)':<10} {'出口IP':<15}")
print("-" * 95)
for r in results:
print(f"{r['目标URL']:<30} {r['使用的代理']:<20} {r['请求状态']:<8} {r['耗时(ms)']:<10} {r['出口IP']:<15}")
return results
def continuous_loop():
"""持续循环执行的主函数"""
loop_count = 0
print("🔄 启动持续循环访问模式")
print(f"循环间隔:{LOOP_INTERVAL}秒")
print(f"最大循环次数:{'无限' if MAX_LOOP_COUNT is None else MAX_LOOP_COUNT}")
print("=" * 60)
# 初始化代理池
init_direct_ip()
refresh_proxy_pool()
try:
while True:
loop_count += 1
print(f"\n🔄 第 {loop_count} 次循环开始")
print("-" * 50)
# 每50次循环刷新一次代理池
if loop_count % 50 == 0:
refresh_proxy_pool()
# 执行单次访问
results = visit_urls_with_proxy_pool()
# 统计本次循环成功率
success_count = sum(1 for r in results if r['请求状态'] == '成功')
total_count = len(results)
success_rate = (success_count / total_count * 100) if total_count > 0 else 0
print(f"\n📈 第 {loop_count} 次循环统计:")
print(f" 总请求数:{total_count}")
print(f" 成功数:{success_count}")
print(f" 成功率:{success_rate:.1f}%")
# 检查是否达到最大循环次数
if MAX_LOOP_COUNT and loop_count >= MAX_LOOP_COUNT:
print(f"\n⏹ 已达到最大循环次数 {MAX_LOOP_COUNT},停止执行")
break
# 等待下一次循环
if LOOP_ENABLED and (MAX_LOOP_COUNT is None or loop_count < MAX_LOOP_COUNT):
print(f"\n⏳ 等待 {LOOP_INTERVAL} 秒后开始下一次循环...")
time.sleep(LOOP_INTERVAL)
except KeyboardInterrupt:
print(f"\n\n⏹ 用户手动停止")
print(f"总计执行循环:{loop_count} 次")
except Exception as e:
print(f"\n❌ 循环执行出错:{str(e)}")
# ===============================================
# 程序入口
# ===============================================
if __name__ == "__main__":
if LOOP_ENABLED:
continuous_loop() # 启用持续循环模式
else:
# 单次执行模式
init_direct_ip()
refresh_proxy_pool()
results = visit_urls_with_proxy_pool()
requests + Playwright 方式
bash
import requests
import time
import re
from fake_useragent import UserAgent
import random
import sys, os
from playwright.sync_api import sync_playwright, TimeoutError as PlaywrightTimeout
class Tee:
def __init__(self, *files):
self.files = files
def write(self, text):
for f in self.files:
f.write(text)
f.flush()
def flush(self):
for f in self.files:
f.flush()
# 明确把日志写在脚本旁边
script_dir = os.path.dirname(os.path.abspath(__file__))
log_path = os.path.join(script_dir, 'proxy_visit.log')
try:
log_file = open(log_path, 'a', encoding='utf-8')
sys.stdout = Tee(sys.stdout, log_file)
print(f"📝 日志文件已创建: {log_path}")
except Exception as e:
print(f"❌ 无法创建日志文件: {e}")
# ==================== 配置区 ====================
# ===============================================
# 循环控制参数
# ===============================================
LOOP_ENABLED = True # 是否启用无限循环
LOOP_INTERVAL = 5 # 每次循环间隔(秒)
MAX_LOOP_COUNT = None # 最大循环次数,None表示无限循环
# ===============================================
# playwright控制参数
# ===============================================
_playwright = None
_browser = None
MIN_STAY = 5 #页面停留最小时间
MAX_STAY = 10 #页面停留最大时间
#完全去掉停留,都改成0,只触发统计但不模拟浏览
HEADLESS_MODE = True #True=无头,后台挂着运行,用这个参数。False=有界面,可用于观察和调试
# ===============================================
# 代理参数
TIMEOUT = 10 # 请求超时时间(秒)
MAX_RETRIES = 3 # 最大重试次数(使用代理时)
USE_FAKE_UA = True # 是否启用随机 User-Agent(需安装 fake-useragent)
# ===============================================
TEST_URL = "http://myip.ipip.net" # 代理验证测试地址
# ===============================================
# 替换为你要访问的目标网址
TARGET_URLS = [
"http://123.com",
"https://1234.com",
"http://12345.top"
]
# 原始代理列表(每行一个 IP:端口)
raw_proxies = """
121.31.233.124:1111
121.31.233.123:11111
121.31.233.122:12111
"""
# ===============================================
# 初始化 User-Agent 生成器
ua = UserAgent() if USE_FAKE_UA else None
PROXY_LIST = []
PROXY_DETAILS = {}
DIRECT_IP = "未知"
# ==================== Playwright 工具函数 ====================
def init_browser():
"""启动无头浏览器"""
global _playwright, _browser
_playwright = sync_playwright().start()
_browser = _playwright.chromium.launch(
headless=HEADLESS_MODE,
#headless=True, #后台静默运行,不显示任何窗口
#headless=False, #会弹出真实的 Chrome 窗口,你甚至能看到页面加载过程
args=[
"--disable-blink-features=AutomationControlled",
"--no-sandbox",
"--disable-dev-shm-usage",
],
)
#if HEADLESS_MODE: # 如果这个变量是 True
# mode_text = "无头模式"
#else: # 否则(False)
# mode_text = "有界面模式"
mode_text = "无头模式" if HEADLESS_MODE else "有界面模式"
print("🌐 Playwright 浏览器已启动({mode_text})")
def close_browser():
"""关闭浏览器"""
global _playwright, _browser
if _browser:
_browser.close()
if _playwright:
_playwright.stop()
print("🌐 浏览器已关闭")
def _parse_proxy_for_playwright(proxy_str):
"""把 'http://ip:port' 或 'http://user:pass@ip:port' 转成 Playwright 代理字典"""
if not proxy_str:
return None
if "://" in proxy_str:
proto, rest = proxy_str.split("://", 1)
else:
proto, rest = "http", proxy_str
if "@" in rest:
auth, hostport = rest.split("@", 1)
user, pwd = auth.split(":", 1)
host, port = hostport.split(":", 1)
return {"server": f"{proto}://{host}:{port}", "username": user, "password": pwd}
else:
host, port = rest.split(":", 1)
return {"server": f"{proto}://{host}:{port}"}
# ==================== 请求函数(requests 版 + Playwright 版) ====================
def make_request(url, proxy=None, timeout=TIMEOUT):
"""
发起单次 HTTP 请求,支持代理和直连
返回: (success: bool, used_proxy: str, elapsed_ms: int, response_text: str)
"""
headers = {"User-Agent": ua.random} if ua else {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"}
start = time.time()
try:
proxies = {"http": proxy, "https": proxy} if proxy else None
resp = requests.get(url, proxies=proxies, headers=headers,
timeout=timeout, allow_redirects=True)
elapsed = round((time.time() - start) * 1000, 2)
if resp.status_code == 200:
preview = resp.text[:200] + "..." if len(resp.text) > 200 else resp.text
return True, proxy or "直连", elapsed, preview
return False, proxy or "直连", elapsed, f"HTTP {resp.status_code}"
except requests.exceptions.Timeout:
elapsed = round((time.time() - start) * 1000, 2)
return False, proxy or "直连", elapsed, "请求超时"
except requests.exceptions.ConnectionError:
elapsed = round((time.time() - start) * 1000, 2)
return False, proxy or "直连", elapsed, "连接失败"
except Exception as e:
elapsed = round((time.time() - start) * 1000, 2)
return False, proxy or "直连", elapsed, str(e)
def make_request_browser(url, proxy=None, timeout=20):
"""
使用 Playwright 浏览器访问目标 URL
返回: (success, used_proxy, elapsed_ms, preview_text)
"""
global _browser
if _browser is None:
return False, proxy or "直连", 0, "浏览器未初始化"
context = None
page = None
start = time.time()
try:
proxy_config = _parse_proxy_for_playwright(proxy)
context = _browser.new_context(
proxy=proxy_config,
user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36",
viewport={"width": 1920, "height": 1080},
locale="zh-CN",
)
page = context.new_page()
response = page.goto(url, timeout=timeout * 1000, wait_until="domcontentloaded")
stay = random.uniform(MIN_STAY, MAX_STAY)
page.wait_for_timeout(int(stay * 1000))
preview = page.content()[:500]
elapsed = int((time.time() - start) * 1000)
return True, proxy or "直连", elapsed, preview
except PlaywrightTimeout:
elapsed = int((time.time() - start) * 1000)
return False, proxy or "直连", elapsed, "页面加载超时"
except Exception as e:
elapsed = int((time.time() - start) * 1000)
return False, proxy or "直连", elapsed, str(e)[:200]
finally:
if page:
page.close()
if context:
context.close()
# ==================== 代理验证 & 池管理 ====================
def validate_proxy(proxy):
"""
验证代理是否有效(用 requests)
返回: (is_valid, elapsed_ms, actual_ip)
"""
success, _, elapsed_ms, text = make_request(TEST_URL, proxy, timeout=8)
if not success:
return False, elapsed_ms, None
match = re.search(r"当前\s*IP\s*[::]\s*(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})", text)
if match:
return True, elapsed_ms, match.group(1)
return True, elapsed_ms, "未能提取IP"
def refresh_proxy_pool():
"""解析 raw_proxies 并验证有效性(仅使用 requests)"""
global PROXY_LIST, PROXY_DETAILS
PROXY_LIST = []
PROXY_DETAILS = {}
lines = [line.strip() for line in raw_proxies.strip().split("\n") if line.strip()]
print(f"📦 读取到 {len(lines)} 个原始代理")
for line in lines:
proxy_url = f"http://{line}"
is_valid, elapsed, ip = validate_proxy(proxy_url)
if is_valid:
PROXY_LIST.append(proxy_url)
PROXY_DETAILS[proxy_url] = {"actual_ip": ip, "latency_ms": elapsed}
print(f" ✅ {line} -> {ip} ({elapsed}ms)")
else:
print(f" ❌ {line} -> 验证失败")
print(f"✅ 代理池刷新完成,有效代理: {len(PROXY_LIST)} 个\n")
def get_random_proxy():
"""从代理列表中随机返回一个代理,若列表为空则返回 None"""
return random.choice(PROXY_LIST) if PROXY_LIST else None
def init_direct_ip():
"""获取本机直连出口IP(用 requests,带重试)"""
global DIRECT_IP
for i in range(2):
ok, _, ip = validate_proxy(None)
if ok and ip and ip != "未能提取IP":
DIRECT_IP = ip
print(f"📌 直连出口IP: {DIRECT_IP}")
return
time.sleep(1)
DIRECT_IP = "获取失败"
print(f"⚠️ 直连出口IP获取失败,后续直连时将实时获取")
# ==================== 主访问逻辑 ====================
def visit_urls_with_proxy_pool():
"""单次循环:使用代理池访问所有目标网址"""
global DIRECT_IP
print("🚀 开始使用代理池访问目标网址...\n")
results = []
for url in TARGET_URLS:
success = False
used_proxy = "直连"
elapsed_ms = 0
response_preview = ""
real_ip = "未知"
# 尝试最多 MAX_RETRIES 次使用不同代理
for attempt in range(MAX_RETRIES):
proxy = get_random_proxy()
if not proxy:
print(f"⚠️ 代理列表为空,跳过代理尝试,直接直连 {url}")
break
proxy_ip = PROXY_DETAILS.get(proxy, {}).get("actual_ip", "未验证")
print(f"🔁 第 {attempt + 1} 次尝试,代理: {proxy} -> 出口IP: {proxy_ip})-> 访问地址: {url}")
#success, used_proxy, elapsed_ms, response_preview = make_request(url, proxy)
success, used_proxy, elapsed_ms, response_preview = make_request_browser(url, proxy)
if success:
real_ip = PROXY_DETAILS.get(proxy, {}).get("actual_ip", "未知")
print(f"✅ 成功!耗时 {elapsed_ms}ms 出口IP: {real_ip}\n")
break
else:
print(f"❌ 失败: {response_preview}\n")
# 若所有代理尝试均失败,则降级为直连,只要尚未成功就尝试直连
if not success:
print(f"📉 所有代理尝试失败,降级为直连访问 {url}")
#success, used_proxy, elapsed_ms, response_preview = make_request(url)
success, used_proxy, elapsed_ms, response_preview = make_request_browser(url)
if success:
real_ip = DIRECT_IP # 直连出口IP
# 兜底:如果 DIRECT_IP 无效,实时获取
if real_ip in ("未知", "获取失败"):
_, _, fallback_ip = validate_proxy(None)
real_ip = fallback_ip or "无法获取"
DIRECT_IP = real_ip
print(f"✅ 直连成功!耗时 {elapsed_ms}ms 出口IP: {real_ip}")
else:
print(f"❌ 直连也失败: {response_preview}\n")
# 记录结果
status = "成功" if success else "失败"
results.append({
"目标URL": url,
"使用的代理": used_proxy,
"请求状态": status,
"耗时(ms)": elapsed_ms,
"出口IP": real_ip
})
print(f"📌 最终结果: {url} | {status} | {elapsed_ms}ms | 代理: {used_proxy} | 出口IP: {real_ip}\n" + "-"*60)
# 输出汇总表格
print("\n📊 本次循环访问结果汇总:")
print(f"{'目标URL':<30} {'使用的代理':<20} {'请求状态':<8} {'耗时(ms)':<10} {'出口IP':<15}")
print("-" * 95)
for r in results:
print(f"{r['目标URL']:<30} {r['使用的代理']:<20} {r['请求状态']:<8} {r['耗时(ms)']:<10} {r['出口IP']:<15}")
return results
# ==================== 循环 & 入口 ====================
def continuous_loop():
"""持续循环执行的主函数"""
loop_count = 0
print("🔄 启动持续循环访问模式")
print(f"循环间隔:{LOOP_INTERVAL}秒")
print(f"最大循环次数:{'无限' if MAX_LOOP_COUNT is None else MAX_LOOP_COUNT}")
print("=" * 60)
# 初始化代理池
init_direct_ip()
refresh_proxy_pool()
init_browser()
try:
while True:
loop_count += 1
print(f"\n🔄 第 {loop_count} 次循环开始")
print("-" * 50)
# 执行单次访问
results = visit_urls_with_proxy_pool()
# 统计本次循环成功率
success_count = sum(1 for r in results if r['请求状态'] == '成功')
total_count = len(results)
success_rate = (success_count / total_count * 100) if total_count > 0 else 0
print(f"\n📈 第 {loop_count} 次循环统计:")
print(f" 总请求数:{total_count}")
print(f" 成功数:{success_count}")
print(f" 成功率:{success_rate:.1f}%")
# 检查是否达到最大循环次数
if MAX_LOOP_COUNT and loop_count >= MAX_LOOP_COUNT:
print(f"\n⏹ 已达到最大循环次数 {MAX_LOOP_COUNT},停止执行")
break
# 每50次循环刷新一次代理池
if loop_count % 50 == 0:
print("🔄 定期刷新代理池...")
refresh_proxy_pool()
# 等待下一次循环
if LOOP_ENABLED and (MAX_LOOP_COUNT is None or loop_count < MAX_LOOP_COUNT):
print(f"\n⏳ 等待 {LOOP_INTERVAL} 秒后开始下一次循环...")
time.sleep(LOOP_INTERVAL)
except KeyboardInterrupt:
print(f"\n\n⏹ 用户手动停止")
print(f"总计执行循环:{loop_count} 次")
close_browser()
except Exception as e:
print(f"\n❌ 循环执行出错:{str(e)}")
close_browser()
# ===============================================
# 程序入口
# ===============================================
def main():
if LOOP_ENABLED:
continuous_loop()
else:
init_direct_ip()
refresh_proxy_pool()
init_browser()
try:
visit_urls_with_proxy_pool()
finally:
close_browser()
if __name__ == "__main__":
main()
| 耗时组成部分 | 实际数据 | 说明 |
|---|---|---|
| 网络加载 (DNS、连接、页面渲染) | 1~3秒 | 这是 Playwright 浏览器真实加载页面的时间 |
| 停留等待 (random.uniform(5, 10)) | 5~10秒 | 这是主动配置的强制停留 |
| 总耗时 | 6~13秒 | 两者相加 |