这段脚本的主要目的是在指定的时间点(如商品秒杀或限时抢购)内尽量准确地刷新页面和点击购买按钮,以提高抢购成功的几率。本文分点介绍该脚本,并说明每个部分的目的,以及脚本中使用的技术。
介绍与总体目的
这个脚本的主要目的是在毫秒级别的精确时间点上刷新商品页面,并自动点击购买按钮,以模拟快速手动操作,来提高在限时抢购活动中的成功率。脚本通过获取服务器时间来确保操作的准确性,避免本地时间不准确带来的误差。
技术使用
- Python:作为脚本编写的主要编程语言,Python通过其丰富的库支持和易读的语法非常适合自动化任务。
- Requests:用于从API获取当前北京时间,通过HTTP请求获取数据。
- datetime和pytz:用于时间处理,确保时间的精度和时区正确。
- Selenium WebDriver:用于模拟浏览器操作,包括页面加载、元素查找和用户交互。
- Chromedriver:用于控制Chrome浏览器的后端驱动。
- logging:用于记录脚本运行过程中的状态和错误信息,便于调试和维护。
- os:用于获取环境变量,便于跨平台操作,例如获取桌面路径。
分点介绍脚本
1. 引入必要的库
import requests
from datetime import datetime, timedelta
import pytz
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import logging
from selenium.webdriver.chrome.service import Service
import os
from time import sleep
from dateutil.parser import isoparse
这些库为脚本提供了时间处理、Web浏览器控制、日志记录和网络请求等功能。
2. 配置日志
# 设置日志级别
logging.basicConfig(level=logging.INFO)
设置日志级别为INFO,便于记录和跟踪脚本执行过程中的各类信息。
3. 获取桌面路径和ChromeDriver路径
# 获取桌面路径
desktop_path = os.path.join(os.path.join(os.environ['USERPROFILE']), 'Desktop')
# 设置 ChromeDriver 路径
chrome_driver_path = r"C:\Users\yuvn\AppData\Local\Google\Chrome\Application\chromedriver.exe"
这些路径配置是为了方便找到桌面路径,并指定ChromeDriver的位置。
4. 配置Chrome浏览器选项
# 配置 Chrome 选项
chrome_options = webdriver.ChromeOptions()
# 启用无头模式
# chrome_options.add_argument("--headless") # 如果希望在后台运行则取消注释
chrome_options.add_argument('--disable-gpu')
chrome_options.add_argument('--no-sandbox')
chrome_options.add_argument('--disable-dev-shm-usage')
配置Chrome浏览器的选项,例如禁止GPU加速、禁用沙箱模式等。
5. 初始化ChromeDriver服务
# 创建 ChromeDriver 服务
service = Service(chrome_driver_path)
使用指定的ChromeDriver路径初始化服务。
6. 打开浏览器并尝试登录
try:
driver = webdriver.Chrome(service=service, options=chrome_options)
url = "https://detail.tmall.com/item.htm?abbucket=12&id=830835918306&ns=1&pisk=gKkmhI4QAjPb62f753yXsrA_qmOJkiw_GVBTWRUwazz5H5z9GVViW4NZH-nxrPuKSlHxBAc5IDisHnw9c-ibCR8pJpeicmwsQfrUUxXz4kmP"
driver.get(url)
sleep(5) # 等待主页加载
# 点击“请登录”,进入登录页
try:
login_button = driver.find_element(By.XPATH, '//*[@id="J_TBPC_POP_detail"]/div/a/div/div[2]/div')
login_button.click()
except Exception as e:
logging.error(f"点击登录按钮失败:{e}")
except Exception as e:
logging.error(f"初始化或者加载主页失败:{e}")
初始化ChromeDriver,打开指定URL页面并尝试登录。
7. 获取北京时间
def get_beijing_time():
try:
response = requests.get("http://worldtimeapi.org/api/timezone/Asia/Shanghai")
if response.status_code == 200:
beijing_time_str = response.json()['datetime']
beijing_time = isoparse(beijing_time_str)
return beijing_time, response.elapsed.total_seconds()
else:
logging.error(f"获取北京时间失败,状态码:{response.status_code}")
except Exception as e:
logging.error(f"获取北京时间失败:{e}")
# 使用本地时间作为备用
logging.warning("使用本地时间作为备用")
beijing_time = datetime.now(pytz.timezone("Asia/Shanghai"))
return beijing_time, 0 # 本地时间不计算延迟
通过HTTP请求获取北京时间作为参考时间,并计算网络延迟。
8. 设置目标时间
# 设置目标时间(带时区)
beijing_tz = pytz.timezone("Asia/Shanghai")
times = "2024-09-28 10:08:00.000" # 这里替换成你需要的时间
target_time = beijing_tz.localize(datetime.strptime(times, "%Y-%m-%d %H:%M:%S.%f"))
指定目标时间,例如秒杀或抢购开始的时间点。
9. 初始化标记
# 初始化标记
has_refreshed = False # 标记是否已经刷新页面
elements_loaded = False # 标记页面元素是否已加载
用于标记页面刷新和元素加载状态的布尔变量。
10. 开始循环检查时间和进行抢购操作
try:
# 开始循环检查时间和进行抢购操作
while True:
now, latency = get_beijing_time()
if not now:
sleep(0.1)
continue
# 减去网络延迟,确保时间更准确
now = now + timedelta(seconds=latency)
# 刷新页面并加载抢购页面元素
if now >= target_time and not has_refreshed:
try:
driver.refresh()
logging.info("页面刷新")
has_refreshed = True
logging.info("加载抢购页面元素")
option_xpath1 = '//div/div[@class="valueItem--GzWd2LsV isDisabled--x_T2h1sh"]' # 瑞红色
option_xpath2 = '//div/div[@class="valueItem--GzWd2LsV isDisabled--x_T2h1sh"]/span' # 1TB
button_xpath = '//div/div[@class="footWrap--LePfCZWd "]/div/div[@class="leftButtons--cys7W_nA"]/button'
# 等待页面元素加载
WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.XPATH, option_xpath1))
)
WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.XPATH, option_xpath2))
)
button = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.XPATH, button_xpath))
)
# 页面元素互动
# option1.click() # 保持注释
# option2.click() # 保持注释
logging.info("页面元素已加载")
elements_loaded = True
except Exception as e:
logging.error(f"刷新页面或者加载抢购页面失败:{e}")
# 在准确时间点执行点击
if now >= target_time - timedelta(milliseconds=500) and elements_loaded:
sleep_time = (target_time - now).total_seconds()
if sleep_time > 0:
logging.info(f"等待 {int(sleep_time * 1000)} 毫秒至命中时间点")
sleep(sleep_time)
try:
button.click()
driver.execute_script("arguments[0].click();", button)
logging.info("抢到啦!!!")
break
except Exception as repeat_e:
logging.error(f"点击失败:{repeat_e}")
sleep(0.001) # 减少点击的间隔时间,增加点击频率
continue
# 增加适当的休眠时间,减少CPU占用
sleep(0.01)
finally:
# 临时保持浏览器打开以检查调试
# driver.quit()
logging.info("脚本运行结束,浏览器保持打开以进行调试")
- 循环获取当前时间:不断循环获取当前的北京时间,并加上网络请求的延迟,确保时间准确。
- 页面刷新:第一次到达交易时间(目标时间)后刷新页面,加载目标页面的元素。
- 页面元素互动:检查并加载各个页面元素,并设置为已加载。
- 点击操作:到达准确时间后用尽可能小的延迟点击页面上指定的按钮,进行秒杀或抢购操作。
- CPU 休眠:在循环中加入适当的睡眠时间,减少CPU的消耗。
11. 调试和结束
finally:
# 临时保持浏览器打开以检查调试
# driver.quit()
logging.info("脚本运行结束,浏览器保持打开以进行调试")
脚本运行结束时,保持浏览器打开以便调试和检查,注释掉driver.quit()
来保持浏览器窗口,以便在调试中查看结果。