1 Star 4 Fork 2

Arnie/叮咚抢菜脚本

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
grabber.py 9.83 KB
一键复制 编辑 原始数据 按行查看 历史
Arnie 提交于 2022-05-18 06:17 . 优化了"抢菜"程序
# -*- coding: utf-8 -*-
"""
叮咚抢菜脚本
==========
通过将移动设备连接至电脑,以自动化测试的方式在设备上模拟点击,从而实现自动抢菜。
@author : Arnie
@license : (c) 2022 Arnie, MIT License
"""
import re
import argparse
import time
from appium import webdriver
from appium.webdriver.common.mobileby import MobileBy
from appium.webdriver.common.appiumby import AppiumBy
import uiautomator2 as u2
import Play_mp3 as mp3
# 默认设备名称: iOS 或 Android
device_name = 'iOS'
# 默认设备编号: iOS UDID 或 Android的设备号
device_code = ''
# WebDriver URL (仅用于iOS)
driver_url = 'http://169.254.75.26:8100'
# 连接设备
def connect_device():
if device_name == 'iOS':
desired_caps = dict()
desired_caps['platformName'] = 'iOS'
desired_caps['automationName'] = 'XCUITest'
desired_caps['udid'] = device_code
driver = webdriver.Remote(driver_url, desired_caps)
else:
driver = u2.connect(device_code)
if not driver.uiautomator.start():
driver.uiautomator.start()
time.sleep(1)
return driver
# 获取元素
def get_element(driver, name, fuzzy = False):
if device_name == 'iOS':
if not fuzzy:
try:
return driver.find_element(MobileBy.NAME, name)
except Exception:
return None
else:
xpath = '//XCUIElementTypeButton[contains(@name,"%s")]' % name
try:
return driver.find_element(AppiumBy.XPATH, xpath)
except Exception:
return None
else:
element = driver(text=name) if not fuzzy else driver(textContains=name)
return element if element.exists else None
# 选择送达时间
def select_time_range(driver, try_times = 0, max_retry = 0):
## 没有运力,尝试捡漏
def retry(try_times, max_retry):
if (max_retry==0 or try_times==max_retry):
mp3.play('sounds/fail.mp3')
if max_retry == 0:
message = '\n😞 没有运力了,进入捡漏阶段\n'
else:
message = '\n😞 捡漏失败,是否继续?\n'
print(message)
chance = input('请输入尝试次数(0: 放弃捡漏):')
if int(chance) <= 0:
exit()
else:
try_times = 0
max_retry = int(chance)
print('\n')
if (try_times > 0):
print('尝试捡漏', try_times, '次')
return { 'try_times': try_times, 'max_retry':max_retry }
if device_name == 'iOS':
xpath = '//XCUIElementTypeOther/XCUIElementTypeOther[2]'
xpath += '/XCUIElementTypeTable[2]/XCUIElementTypeCell'
selectable = False
try:
items = driver.find_elements(MobileBy.XPATH, xpath)
items_count = len(items)
if items_count == 0:
driver.find_element(AppiumBy.ACCESSIBILITY_ID,'关闭').click()
for i in range( items_count ):
item = items[i]
if not get_element(item,'已约满'):
selectable = True
print('👌 有运力,加油!')
item.click()
if get_element(driver, '立即支付'):
print('点击 “立即支付”')
get_element(driver, '立即支付').click()
if not selectable and i == items_count-1 :
retry = retry(try_times, max_retry)
try_times = retry['try_times']
max_retry = retry['max_retry']
driver.find_element(AppiumBy.ACCESSIBILITY_ID,'关闭').click()
driver.find_element(AppiumBy.ACCESSIBILITY_ID,'返回').click()
except Exception: None
else:
xpath_mode = '//*[@resource-id="com.yaya.zone:id/%s"]'
selector_xpath = xpath_mode % 'rv_selected_hour'
close_xpath = xpath_mode % 'iv_dialog_select_time_close'
back_xpath = xpath_mode % 'iv_order_back'
selector = driver.xpath(selector_xpath)
if not selector.exists:
driver.xpath(close_xpath).click_exists(timeout=1)
else:
items_count = selector.get(timeout=1).info.get('childCount', 0)
item_xpath_mode = selector_xpath+'/android.view.ViewGroup[%d]'
selectable = False
for i in range(items_count):
item = driver.xpath(item_xpath_mode % (i+1))
if not item.exists:
continue
if item.get(timeout=1).info.get('enabled','') != 'false':
selectable = True
print('👌 有运力,加油!')
item.click_exists(timeout=1)
if get_element(driver, '立即支付'):
print('点击 “立即支付”')
get_element(driver, '立即支付').click()
if not selectable and i == items_count-1 :
retry = retry(try_times, max_retry)
try_times = retry['try_times']
max_retry = retry['max_retry']
driver.xpath(close_xpath).click_exists(timeout=1)
driver.xpath(back_xpath).click_exists(timeout=1)
return { 'try_times':try_times+1, 'max_retry':max_retry }
# 抢菜
def grab_food(test = False):
driver = connect_device()
start = time.time()
count = 1
fails = 1
try_times = 0
max_retry = 0
while True:
begin = time.time()
if get_element(driver, '去结算(', True):
print('点击 “去结算”')
get_element(driver, '去结算(', True).click()
if get_element(driver, '我知道了'):
print('点击 “我知道了”')
get_element(driver, '我知道了').click()
if get_element(driver, '重新加载'):
print('点击 “重新加载”')
get_element(driver, '重新加载').click()
if get_element(driver, '请选择送达时间'):
print('重新选择送达时间')
get_element(driver, '请选择送达时间').click()
if get_element(driver, '下单失败'):
print('下单失败,第', fails, '次')
fails += 1
if get_element(driver, '返回购物车'):
print('点击 “返回购物车”')
get_element(driver, '返回购物车').click()
else:
if get_element(driver, '立即支付'):
print('点击 “立即支付”')
get_element(driver, '立即支付').click()
if get_element(driver, '选择送达时间'):
print('选择送达时间')
try_select = select_time_range(driver, try_times, max_retry)
try_times = try_select['try_times']
max_retry = try_select['max_retry']
# 支付宝
if get_element(driver, '确认交易'):
print('点击 “确认交易”')
get_element(driver, '确认交易').click()
mp3.play('sounds/success.mp3')
print('\n✌️ “抢菜”成功,退出脚本\n')
exit()
# 微信支付
if get_element(driver, '确认支付'):
print('点击 “确认支付”')
get_element(driver, '确认支付').click()
mp3.play('sounds/success.mp3')
print('\n✌️ “抢菜”成功,退出脚本\n')
exit()
duration = '%.6f' % (time.time()-begin)
total_duration = '%.6f' % ((time.time()-start) / 60)
print ('本次操作时间:', duration, '秒')
print ('总共耗费时间:', total_duration, '分钟,第', count, '次')
if test and time.time()-start >= 60:
print('\n测试结束,退出脚本\n')
exit()
count += 1
# 运行
def run(test = False):
print('\n开始“抢菜” >>>\n')
mp3.play('sounds/start.mp3')
while True:
try:
grab_food(test)
except Exception as e:
print(e)
mp3.play('sounds/fail.mp3')
time.sleep(5)
# 值守
def wait():
print('\n开始值守任务,请确认已取消电脑的自动休眠功能\n')
driver = connect_device()
if device_name == 'iOS':
touchend = 560; duration = 100
else:
touchend = 960; duration = 0.1
while True:
hour = time.localtime().tm_hour
minute = time.localtime().tm_min
if hour>22 or hour<5 or (hour==5 and minute<55):
driver.swipe(200,360, 200,touchend, duration)
time.sleep(15)
else:
run()
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='manual to this script')
parser.add_argument('--device', type=str, default='')
parser.add_argument('--code', type=str, default='')
args = parser.parse_args()
if args.device: device_name = args.device
if args.code: device_code = args.code
if device_name not in ['iOS', 'Android']:
print('\n⚠️ 设备名称仅限填写 iOS 和 Android\n')
exit()
if not re.search('^[\w-]{8,}|[\d+\.]{3}\d+:\d+$', device_code):
print('\n⚠️ 设备编号格式错误\n')
exit()
hour = time.localtime().tm_hour
minute = time.localtime().tm_min
if hour>22 or hour<5 or (hour==5 and minute<55):
tips = '\n现在还没到“抢菜”时间,请选择您的策略:\n'
tips += '\n 1. 程序值守任务,5:55 开始自动“抢菜” 2. 测试60秒 3. 退出程序\n'
print(tips)
plan = input('请输入您的选项:')
if plan == '1':
wait()
else:
if plan == '2':
run(True)
else:
print('\n')
exit()
run()
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
Python
1
https://gitee.com/arnie/dingdong-grabber.git
git@gitee.com:arnie/dingdong-grabber.git
arnie
dingdong-grabber
叮咚抢菜脚本
master

搜索帮助