1. 电商上架的效率痛点与自动化机遇
去年双十一前,我们团队用妙手ERP给3000个SKU铺货时遇到了一个致命问题——系统在最后的上架环节平均每个商品要卡顿6-8秒。当商品数量突破四位数时,这种延迟直接导致运营团队被迫通宵加班。这让我意识到,ERP系统在商品信息管理方面确实强大,但在电商平台前端交互这个"最后一公里"上,往往存在难以克服的性能瓶颈。
通过抓包分析发现,这种延迟主要来自三个方面:首先是平台反爬机制导致的随机等待时间,其次是图片上传时的压缩处理耗时,最致命的是页面元素加载的不确定性。传统ERP的解决方案是简单粗暴地增加线程,但这很容易触发平台的风控机制。而Python+RPA的组合恰好能针对性地解决这些问题——用Playwright模拟真人操作绕过风控,用异步IO处理图片上传,再用智能等待策略应对页面延迟。
2. 技术选型:为什么是Python+Playwright
2.1 主流RPA工具对比测试
我们实测了三种技术方案:影刀RPA、Selenium和Playwright。在淘宝商品上架场景下,影刀虽然学习成本低,但处理复杂页面元素时灵活性不足;Selenium的稳定性虽好,但执行速度比Playwright慢40%左右。Playwright的几大优势特别适合电商场景:
- 原生支持多语言(包括Python)
- 自动等待元素机制
- 跨平台一致性(尤其对付淘宝/京东那些随浏览器版本变化的DOM结构)
- 轻量级无头模式
python复制# Playwright基础配置示例
from playwright.sync_api import sync_playwright
def run(playwright):
chromium = playwright.chromium
browser = chromium.launch(headless=False) # 调试时可关闭无头模式
context = browser.new_context(
user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36...'
)
page = context.new_page()
# 关键配置:设置超时和等待策略
page.set_default_timeout(60000)
page.set_default_navigation_timeout(60000)
2.2 与妙手ERP的对接方案
通过分析妙手ERP的数据库结构,我们发现其商品数据表(product_items)中有完整的平台映射字段。最佳实践是通过中间件读取ERP的MySQL数据,转化为平台所需的JSON格式:
python复制import pymysql
import json
def get_erp_data():
connection = pymysql.connect(
host='erp_host',
user='erp_user',
password='erp_password',
db='erp_db',
charset='utf8mb4'
)
try:
with connection.cursor() as cursor:
sql = "SELECT * FROM product_items WHERE status='pending'"
cursor.execute(sql)
return cursor.fetchall()
finally:
connection.close()
def transform_to_platform_format(erp_data):
# 转换逻辑示例:淘宝SKU格式
return {
"title": erp_data[1],
"price": float(erp_data[3]),
"stock": int(erp_data[4]),
# 其他字段映射...
}
3. 核心自动化流程实现
3.1 登录态的持久化处理
电商平台最麻烦的是登录验证。我们采用cookie持久化方案,配合验证码识别服务:
python复制import pickle
from playwright.sync_api import sync_playwright
def save_cookies(context, platform):
cookies = context.cookies()
with open(f'{platform}_cookies.pkl', 'wb') as f:
pickle.dump(cookies, f)
def load_cookies(context, platform):
try:
with open(f'{platform}_cookies.pkl', 'rb') as f:
cookies = pickle.load(f)
context.add_cookies(cookies)
return True
except:
return False
3.2 商品图片上传优化
图片上传是最大的时间瓶颈。我们开发了多线程压缩+预上传方案:
- 使用Pillow进行自适应压缩(保持大小在平台限制的90%左右)
- 提前上传到平台图片空间(非商品页)
- 上架时直接引用图片URL
python复制from PIL import Image
from io import BytesIO
import threading
def compress_image(image_path, target_size_kb=800):
img = Image.open(image_path)
# 动态调整压缩质量
quality = 95
while True:
buffer = BytesIO()
img.save(buffer, format='JPEG', quality=quality)
if len(buffer.getvalue()) <= target_size_kb * 1024 or quality <= 50:
break
quality -= 5
return buffer.getvalue()
3.3 智能等待策略
针对不同平台开发了元素等待策略:
python复制def smart_wait(page, platform):
if platform == 'taobao':
# 淘宝需要特别等待价格输入框
page.wait_for_selector("//input[@name='price']", state='attached')
# 随机延迟模拟人工
page.wait_for_timeout(random.randint(800, 1500))
elif platform == 'jd':
# 京东需要等待类目树加载
page.wait_for_selector(".category-list", state='visible')
4. 异常处理与风控规避
4.1 验证码破解方案
当触发平台验证时,我们的处理流程:
- 自动截图保存当前页面
- 调用第三方验证码识别服务(平均2秒/次)
- 自动填充验证码并继续流程
- 失败时自动切换到备用账号
python复制def handle_captcha(page):
captcha_selector = "//img[contains(@src,'captcha')]"
if page.is_visible(captcha_selector):
screenshot = page.screenshot(type='png')
captcha_text = call_captcha_api(screenshot) # 调用第三方API
page.fill("//input[@name='captcha']", captcha_text)
page.click("//button[contains(text(),'确认')]")
return page.is_visible(captcha_selector) # 返回是否仍然存在
return False
4.2 操作指纹模拟
通过以下方式降低被识别风险:
- 随机化鼠标移动轨迹
- 动态更换UserAgent
- 模拟人工输入速度(每个字符间隔100-300ms)
- 随机操作间隔时间
python复制def human_type(page, selector, text):
for char in text:
page.type(selector, char, delay=random.randint(100, 300))
# 随机加入错误并修正
if random.random() < 0.1:
page.type(selector, random.choice('abcdefgh'), delay=50)
page.keyboard.press('Backspace')
5. 性能优化实战数据
经过三个月的迭代,我们的方案在淘宝平台上实现了:
- 平均上架时间从6.8秒降至1.2秒
- 成功率从78%提升到99.6%
- 单机日均处理量从300件提升到1500件
关键优化点包括:
- 采用连接池管理数据库连接
- 实现图片预上传缓存机制
- 开发自动化重试策略(最多3次)
- 引入内存缓存减少ERP查询
python复制# 连接池配置示例
from DBUtils.PooledDB import PooledDB
mysql_pool = PooledDB(
creator=pymysql,
maxconnections=10,
host='erp_host',
user='erp_user',
password='erp_password',
db='erp_db'
)
def get_erp_data_pooled():
connection = mysql_pool.connection()
try:
with connection.cursor() as cursor:
sql = "SELECT * FROM product_items WHERE status='pending'"
cursor.execute(sql)
return cursor.fetchall()
finally:
connection.close()
6. 部署与监控方案
6.1 分布式任务队列
使用Redis + RQ实现任务分发:
python复制from redis import Redis
from rq import Queue
redis_conn = Redis(host='redis_host')
task_queue = Queue(connection=redis_conn)
def dispatch_task(erp_id_list):
for erp_id in erp_id_list:
task_queue.enqueue('upload_product', erp_id)
6.2 监控看板实现
基于Prometheus + Grafana搭建监控系统,关键指标:
- 任务成功率
- 平均处理时间
- 平台限流次数
- 验证码出现频率
python复制from prometheus_client import Counter, Gauge
# 定义指标
TASKS_TOTAL = Counter('tasks_total', 'Total tasks processed')
TASKS_FAILED = Counter('tasks_failed', 'Failed tasks')
PROCESS_TIME = Gauge('process_time_seconds', 'Processing time per task')
@PROCESS_TIME.time()
def upload_product(erp_id):
try:
# 业务逻辑...
TASKS_TOTAL.inc()
except Exception as e:
TASKS_FAILED.inc()
raise
7. 实际踩坑经验
在京东平台实施时,我们遇到了最棘手的三个问题:
-
类目选择陷阱:京东的类目树会根据账号类型动态变化。解决方案是预先缓存每个账号的类目结构,并实现自动匹配算法。
-
属性值依赖:某些属性选项会动态加载。我们开发了递归等待机制:
python复制def wait_for_dependent_options(page, main_selector, dependent_selector):
page.select_option(main_selector, 'value')
start_time = time.time()
while time.time() - start_time < 10: # 最多等待10秒
options = page.query_selector_all(f"{dependent_selector} > option")
if len(options) > 1: # 第一个是"请选择"
return True
page.wait_for_timeout(500)
return False
- 商品编码冲突:京东对商品编码有严格校验。最终方案是先查询后创建:
python复制def check_product_exists(page, sku):
page.goto(f"https://item.jd.com/{sku}.html")
return not page.is_visible(".error-page") # 非错误页表示商品存在
这套系统上线后,我们的运营团队在去年双十一期间实现了48小时内完成2.3万件商品上架,错误率低于0.2%。最关键的收获是:ERP系统适合做数据管理,而前端交互这种需要"人性化"的操作,交给RPA反而能产生奇效。
