电商桌面自动化实战:用RPA实现抖店批量铺货

电商桌面自动化实战:用RPA实现抖店批量铺货


做电商多店铺运营的都知道,铺货是最典型的重复性劳动------筛选、编辑、定价、发布,每个商品都要走一遍相同的流程。

本文从技术角度解析如何用桌面自动化(RPA)实现抖店批量铺货,以及实际落地中遇到的几个关键问题。


一、铺货自动化的核心流程

手动铺货的完整流程:

  1. 打开抖店货源页面
  2. 按条件筛选商品(类目、价格、好评率、发货率等)
  3. 逐个点击"去铺货"
  4. 进入商品编辑页
  5. 处理主图(裁剪比例、生成视频)
  6. 计算并设置价格
  7. 填写商品信息
  8. 发布

自动化需要解决的,就是把这8个步骤全部程序化。


二、技术架构设计

2.1 整体架构

复制代码
┌─────────────────────────────────────────┐
│           用户交互层                    │
│   对话式UI(自然语言指令解析)           │
├─────────────────────────────────────────┤
│           任务调度层                    │
│   任务队列 + 排队机制 + 定时触发         │
├─────────────────────────────────────────┤
│           自动化执行层                  │
│   浏览器自动化 + 页面元素操作            │
├─────────────────────────────────────────┤
│           数据管理层                    │
│   本地SQLite + 独立浏览器配置           │
└─────────────────────────────────────────┘

核心设计要点:

  • 每个店铺独立浏览器实例,避免Cookie/Session串号
  • 任务队列机制,同一店铺的任务串行执行,避免并发冲突
  • 对话式指令解析,降低用户学习成本

2.2 独立浏览器环境

多店铺管理的核心技术难点是浏览器隔离:

python 复制代码
import os

class BrowserManager:
    """每个店铺使用独立的浏览器配置目录"""

    def __init__(self, base_data_dir: str):
        self.base_data_dir = base_data_dir

    def get_browser_profile(self, shop_id: str) -> str:
        """
        为每个店铺返回独立的浏览器配置目录
        确保Cookie、Session、缓存完全隔离
        """
        profile_dir = os.path.join(
            self.base_data_dir, 'browsers', f'shop_{shop_id}'
        )
        os.makedirs(profile_dir, exist_ok=True)
        return profile_dir

    def launch_browser(self, shop_id: str, url: str):
        """启动指定店铺的浏览器实例"""
        profile = self.get_browser_profile(shop_id)
        # 使用独立的用户数据目录启动浏览器
        browser = launch(
            headless=False,
            user_data_dir=profile,
            args=['--no-sandbox']
        )
        page = browser.new_page()
        page.goto(url)
        return browser, page

三、选品策略的实现

3.1 筛选条件数据模型

python 复制代码
from dataclasses import dataclass, field
from typing import Optional

@dataclass
class SelectionStrategy:
    """选品策略配置"""
    name: str                          # 策略名称
    category: Optional[str] = None     # 类目筛选
    price_min: float = 0               # 最低价格
    price_max: float = 9999            # 最高价格
    min_rating: float = 0.95           # 最低好评率
    min_ship_rate: float = 0.98        # 最低发货率
    max_return_rate: float = 0.05      # 最高退货率
    free_shipping: bool = True         # 是否包邮
    seven_day_return: bool = True      # 是否7天无理由
    blocked_suppliers: list = field(default_factory=list)  # 屏蔽供应商
    blocked_keywords: list = field(default_factory=list)   # 屏蔽关键词
    target_count: int = 50             # 目标铺货数量

    def should_include(self, product: dict) -> bool:
        """判断商品是否符合筛选条件"""
        # 供应商屏蔽
        if product.get('supplier') in self.blocked_suppliers:
            return False

        # 关键词屏蔽
        title = product.get('title', '')
        for kw in self.blocked_keywords:
            if kw in title:
                return False

        # 条件筛选
        if not (self.price_min <= product.get('price', 0) <= self.price_max):
            return False
        if product.get('rating', 0) < self.min_rating:
            return False
        if product.get('ship_rate', 0) < self.min_ship_rate:
            return False
        if product.get('return_rate', 1) > self.max_return_rate:
            return False

        return True

3.2 自动筛选与执行

python 复制代码
class ListingBot:
    """铺货自动化执行引擎"""

    def __init__(self, strategy: SelectionStrategy, browser_manager: BrowserManager):
        self.strategy = strategy
        self.browser_mgr = browser_manager
        self.success_count = 0
        self.fail_count = 0

    async def run(self, shop_id: str):
        """执行完整的铺货流程"""
        browser, page = self.browser_mgr.launch_browser(
            shop_id,
            'https://fxg.jinritemai.com/ffp/goods/source'
        )

        # 第一步:按策略筛选商品
        products = await self._filter_products(page)

        # 第二步:逐个执行铺货
        for product in products[:self.strategy.target_count]:
            try:
                await self._list_product(page, product)
                self.success_count += 1
            except Exception as e:
                self.fail_count += 1
                self._log(f'商品 {product["title"]} 铺货失败: {e}')

        await browser.close()

    async def _filter_products(self, page) -> list:
        """在货源页面按策略条件筛选商品"""
        products = []
        items = await page.query_selector_all('.product-item')

        for item in items:
            product_data = {
                'title': await item.inner_text('.product-title'),
                'price': float(await item.inner_text('.price')),
                'rating': float(await item.inner_text('.rating')),
                'supplier': await item.inner_text('.supplier-name'),
            }

            if self.strategy.should_include(product_data):
                products.append(product_data)

        return products

    async def _list_product(self, page, product: dict):
        """执行单个商品的铺货操作"""
        # 点击"去铺货"
        await page.click('.list-btn')
        await page.wait_for_load_state('networkidle')

        # 设置价格(加价逻辑)
        base_price = product['price']
        final_price = base_price * (1 + self.markup_rate / 100) + self.fixed_markup
        await page.fill('.price-input', str(round(final_price, 2)))

        # 处理主图
        await self._process_main_image(page)

        # 发布
        await page.click('.publish-btn')
        await page.wait_for_selector('.success-toast')

四、定价逻辑的实现

python 复制代码
class PriceCalculator:
    """定价计算器"""

    def __init__(self, markup_rate: float = 100, fixed_markup: float = 0):
        """
        markup_rate: 加价百分比(100 = 基准价的2倍)
        fixed_markup: 固定加价金额
        """
        self.markup_rate = markup_rate
        self.fixed_markup = fixed_markup

    def calculate(self, supply_price: float) -> float:
        """
        计算最终售价
        供货价50 + 加价100% + 固定加价10 = 50*2 + 10 = 110
        """
        return supply_price * (1 + self.markup_rate / 100) + self.fixed_markup

五、任务队列与调度

多店铺场景下,任务调度是关键:

python 复制代码
import asyncio
from collections import defaultdict

class TaskScheduler:
    """
    任务调度器
    同一店铺的任务串行执行,不同店铺的任务并行执行
    """

    def __init__(self):
        self.queues = defaultdict(asyncio.Queue)  # 每个店铺一个队列
        self.running = {}

    async def submit(self, shop_id: str, task):
        """提交任务到指定店铺的队列"""
        await self.queues[shop_id].put(task)

    async def run_shop(self, shop_id: str):
        """消费指定店铺的任务队列"""
        while True:
            task = await self.queues[shop_id].get()
            self.running[shop_id] = task
            try:
                await task.execute()
            finally:
                self.running.pop(shop_id, None)
                self.queues[shop_id].task_done()

    def is_shop_busy(self, shop_id: str) -> bool:
        """检查店铺是否正在执行任务"""
        return shop_id in self.running

六、落地过程中的几个问题

问题一:页面元素变化导致脚本失效

抖店的页面结构会不定期更新,选择器会失效。建议用文本匹配+属性匹配的组合定位,而不是依赖固定的CSS选择器。

问题二:操作频率过高被检测

建议每次操作之间加随机延迟(2-5秒),模拟人工操作节奏。任务之间也要有间隔。

问题三:浏览器进程泄漏

长时间运行后,浏览器进程可能没有正确关闭。建议定期检查并清理僵尸进程。

问题四:登录状态过期

Cookie和Session有有效期,需要定期检测登录状态,过期后提醒用户重新授权。


七、总结

电商铺货自动化的核心难点不是技术实现,而是稳定性和可维护性。页面结构会变、登录状态会过期、操作频率要控制------这些都是生产环境中必须处理的问题。

建议采用"对话式UI + 任务队列 + 独立浏览器"的架构,既能降低用户操作门槛,又能保证多店铺并发的稳定性。

相关推荐
人道领域1 小时前
【LeetCode刷题日记】递归与回溯实战 257.二叉树的所有路径——一篇文章彻底搞懂回溯
开发语言·python·算法·leetcode
电子科技圈1 小时前
XMOS推出适配VS Code编辑器的XTC工具插件
人工智能·mcu·编辑器·视觉检测·音视频·语音识别·视频编解码
Gofarlic_OMS1 小时前
Mastercam浮动许可利用率低:软件许可浪费,回收再分配
java·大数据·开发语言·架构·制造
红茶要加冰1 小时前
三、条件测试
linux·运维·服务器
云栖梦泽在1 小时前
AI安全实战:AI供应链安全防护的实战案例
大数据·人工智能·安全
2601_955781981 小时前
飞书远程控机:OpenClaw+AI机器人配置全攻略
人工智能·机器人·飞书·open claw部署
吃好睡好便好1 小时前
在Matlab中用sphere( )函数绘制球面图
开发语言·前端·javascript·学习·算法·matlab·信息可视化
lynnlovemin1 小时前
二分查找与二分答案算法详解(基于C++实现)
c语言·开发语言·算法·二分查找·二分答案
开开心心就好1 小时前
带可视化界面的目录文件合并工具
java·运维·科技·游戏·tomcat·自动化·powerpoint