文章附件下载:www.pan38.com/dow/share.p… 提取密码:8641
Python端采用请求级联模式,通过Cookies维持会话,支持商品搜索和批量下单 AutoJS脚本实现移动端自动化操作,包含元素定位、价格筛选和下单流程 价格比较算法采用正则表达式匹配,支持滑动列表动态加载 异常处理机制包含最大重试次数和错误日志记录 随机延迟设计避免操作频率过高触发风控
import requests import json import time import random from typing import List, Dict
class PDDOrderBot: def init(self, cookies: str, user_agent: str = None): self.session = requests.Session() self.base_url = "mobile.yangkeduo.com" self.cookies = self._parse_cookies(cookies) self.headers = { 'User-Agent': user_agent or 'Mozilla/5.0', 'Referer': self.base_url + '/', 'Accept': 'application/json' }
def _parse_cookies(self, cookie_str: str) -> Dict:
return {k:v for k,v in [item.split('=',1)
for item in cookie_str.split(';') if '=' in item]}
def search_products(self, keyword: str) -> List[Dict]:
params = {
'keyword': keyword,
'page': 1,
'size': 50,
'sort_type': 1 # 按价格排序
}
try:
resp = self.session.get(
f"{self.base_url}/search",
params=params,
headers=self.headers,
cookies=self.cookies
)
return [{
'goods_id': item['goods_id'],
'title': item['goods_name'],
'price': float(item['normal_price'])/100,
'sales': item['sales']
} for item in resp.json()['items']]
except Exception as e:
print(f"搜索失败: {str(e)}")
return []
def batch_create_orders(self, goods_list: List[Dict],
address_id: str, quantity: int = 1) -> bool:
order_results = []
for goods in goods_list:
if goods['price'] > MAX_PRICE: # 价格过滤
continue
data = {
'goods_id': goods['goods_id'],
'address_id': address_id,
'goods_number': quantity,
'source_type': 26
}
try:
resp = self.session.post(
f"{self.base_url}/order/create",
json=data,
headers=self.headers,
cookies=self.cookies
)
if resp.json().get('error_code') == 0:
order_results.append(goods['goods_id'])
time.sleep(random.uniform(1, 3)) # 随机延迟
except Exception as e:
print(f"下单失败: {str(e)}")
return len(order_results) > 0
import requests import json import time import random from typing import List, Dict
class PDDOrderBot: def init(self, cookies: str, user_agent: str = None): self.session = requests.Session() self.base_url = "mobile.yangkeduo.com" self.cookies = self._parse_cookies(cookies) self.headers = { 'User-Agent': user_agent or 'Mozilla/5.0', 'Referer': self.base_url + '/', 'Accept': 'application/json' }
def _parse_cookies(self, cookie_str: str) -> Dict:
return {k:v for k,v in [item.split('=',1)
for item in cookie_str.split(';') if '=' in item]}
def search_products(self, keyword: str) -> List[Dict]:
params = {
'keyword': keyword,
'page': 1,
'size': 50,
'sort_type': 1 # 按价格排序
}
try:
resp = self.session.get(
f"{self.base_url}/search",
params=params,
headers=self.headers,
cookies=self.cookies
)
return [{
'goods_id': item['goods_id'],
'title': item['goods_name'],
'price': float(item['normal_price'])/100,
'sales': item['sales']
} for item in resp.json()['items']]
except Exception as e:
print(f"搜索失败: {str(e)}")
return []
def batch_create_orders(self, goods_list: List[Dict],
address_id: str, quantity: int = 1) -> bool:
order_results = []
for goods in goods_list:
if goods['price'] > MAX_PRICE: # 价格过滤
continue
data = {
'goods_id': goods['goods_id'],
'address_id': address_id,
'goods_number': quantity,
'source_type': 26
}
try:
resp = self.session.post(
f"{self.base_url}/order/create",
json=data,
headers=self.headers,
cookies=self.cookies
)
if resp.json().get('error_code') == 0:
order_results.append(goods['goods_id'])
time.sleep(random.uniform(1, 3)) # 随机延迟
except Exception as e:
print(f"下单失败: {str(e)}")
return len(order_results) > 0
// ====================== // 拼多多自动化脚本增强版 // AutoJS 4.1.1+ 兼容 // ====================== const CONFIG = { maxRetry: 3, waitTime: 2000, debugMode: true };
auto.waitFor(); launchApp("拼多多"); sleep(CONFIG.waitTime);
class PddAutomator { constructor() { this.retryCount = 0; }
searchProduct(keyword) {
try {
let searchInput = id("search_input").findOne(CONFIG.waitTime);
if (searchInput) {
searchInput.setText(keyword);
sleep(1000);
id("search_button").findOne().click();
return true;
}
} catch (e) {
this._handleError(e, "searchProduct");
}
return false;
}
getProductList() {
let products = [];
try {
let items = className("android.view.View").depth(15).find();
items.forEach(item => {
let priceElement = item.findOne(
className("android.widget.TextView")
.textMatches(/¥\s*\d+\.\d{2}/));
if (priceElement) {
let title = item.findOne(
className("android.widget.TextView").depth(16));
products.push({
title: title ? title.text() : "未知商品",
price: parseFloat(priceElement.text().replace(/[^\d.]/g, '')),
element: item
});
}
});
} catch (e) {
this._handleError(e, "getProductList");
}
return products;
}
selectLowestPrice(products) {
if (!products || products.length === 0) return null;
return products.sort((a, b) => a.price - b.price)[0];
}
autoCheckout(product) {
try {
product.element.click();
sleep(CONFIG.waitTime * 2);
this._selectSpecifications();
let addCartBtn = text("加入购物车").findOne(CONFIG.waitTime);
if (addCartBtn) {
addCartBtn.click();
sleep(CONFIG.waitTime);
return true;
}
} catch (e) {
this._handleError(e, "autoCheckout");
}
return false;
}
_selectSpecifications() {
let specBtn = text("选择规格").findOne(CONFIG.waitTime);
if (specBtn) {
specBtn.click();
sleep(1000);
let firstSpec = className("android.view.View")
.depth(20).clickable().findOne(CONFIG.waitTime);
if (firstSpec) firstSpec.click();
sleep(500);
text("确定").findOne(CONFIG.waitTime)?.click();
}
}
}