影刀RPA实战案例:拼多多商品数据自动化采集与价格清洗

今天直接上一个完整的实战案例。拼多多商品数据采集是我被问得最多的问题,也是我踩坑最多的地方。

这篇文章不讲零散指令,直接给一个从登录到采集到清洗的完整流程,你复制调整后就能跑。重点讲拼多多特有的几个坑:移动端页面结构、价格区间清洗、翻页逻辑。

picture.image


先说这个流程能做什么

picture.image

输入:一个Excel文件,里面有一列商品关键词 输出:每个关键词对应的商品名称、价格区间、销量、店铺名、链接

适用范围: 竞品价格监控、选品分析、供应商比价

picture.image


第一步:环境准备与登录态处理

picture.image 拼多多采集最烦人的是登录态。PC端网页频繁操作容易被弹出验证码,手机端页面相对友好。

我的选型: 用影刀的移动端浏览器环境模拟手机访问 m.pinduoduo.com

影刀RPA实操路径: 新建流程 → 选择“网页自动化” → 浏览器类型下拉选择“移动端(安卓)”。

picture.image

登录态保持策略:

# 步骤1:打开拼多多移动端首页

![picture.image](https://p3-volc-community-sign.byteimg.com/tos-cn-i-tlddhu82om/4bbf4dc51b7e4d9a9eb58189fdcd931c~tplv-tlddhu82om-image.image?=&rk3s=8031ce6d&x-expires=1783352702&x-signature=twOM2Sq3zHG0CFJwGYvOG1%2Bl7YQ%3D)
打开网页("https://m.pinduoduo.com", 打开方式="新建标签页")

# 步骤2:检测登录态
# 捕获元素:判断是否存在“我的”按钮(已登录状态有个人入口)
//*[contains(text(),"我的")]

![picture.image](https://p3-volc-community-sign.byteimg.com/tos-cn-i-tlddhu82om/6d70124ea8744710b68e1780fda03799~tplv-tlddhu82om-image.image?=&rk3s=8031ce6d&x-expires=1783352702&x-signature=UhAdW8QNsCVdT%2BaYvWmIZjg7Ulc%3D)

# 步骤3:如果未登录,执行登录
如果 判断元素是否存在("//*[contains(text(),'登录')]") == True:
    # 点击登录按钮
    点击元素("//*[contains(text(),'登录')]")
    
![picture.image](https://p3-volc-community-sign.byteimg.com/tos-cn-i-tlddhu82om/2385fbda3b2f4f51ab67328733f8586f~tplv-tlddhu82om-image.image?=&rk3s=8031ce6d&x-expires=1783352702&x-signature=qT9wk7kn61GG0M7HME4yvSYX7LY%3D)
    # 等待登录页加载
    等待元素加载("//input[@placeholder='请输入手机号']", 超时时间=10秒)
    # 输入账号密码(注意:这里用模拟输入而不是直接输入)
    模拟输入("//input[@placeholder='请输入手机号']", 账号变量)
    模拟输入("//input[@type='password']", 密码变量)
    点击元素("//*[contains(text(),'登录')]")
    # 等待登录完成
    等待(3秒)
    输出日志("登录完成")
否则:
    输出日志("已登录,跳过登录步骤")
结束如果

容易踩的坑: 拼多多移动端的密码输入框用 input 指令直接写入有时不生效,用“模拟输入”更稳。另外登录后可能跳出滑块验证,这部分社区版处理不了,创业版有滑块识别模块。


第二步:搜索关键词并获取商品列表

核心逻辑: 输入关键词 → 点击搜索 → 等待结果加载 → 获取商品卡片列表。

# 先读取Excel获取关键词列表
读取Excel文件("C:/data/keywords.xlsx", 输出变量=keywords_data)
# 假设关键词在第一列,从第二行开始
关键词列表 = keywords_data[1:]


![picture.image](https://p3-volc-community-sign.byteimg.com/tos-cn-i-tlddhu82om/07222cc08343409eb82617dd02858342~tplv-tlddhu82om-image.image?=&rk3s=8031ce6d&x-expires=1783352702&x-signature=lZrlBR5FzjKU%2FssaIUvRdAQke1Q%3D)
# 按列表循环每个关键词
按列表循环(关键词列表, 循环项=keyword_row):
    keyword = keyword_row[0]  # 第一列是关键词
    
    # ----- 执行搜索 -----
    # 捕获元素:搜索框(移动端通常是顶部输入框)
    //input[@class="search-input" or contains(@placeholder,"搜索")]
    点击元素(搜索框)
    # 清空输入框(先全选再删除)
    模拟按键("Ctrl+A")
    模拟按键("Backspace")
    # 输入关键词
    模拟输入(搜索框, keyword)
    # 点击搜索按钮
    //*[contains(@class,"search-btn") or contains(text(),"搜索")]
    点击元素(搜索按钮)
    
    # 等待搜索结果加载
    等待(3秒)
    
    # ----- 获取商品卡片列表 -----
    # 捕获元素:所有商品卡片
    获取相似元素列表("//div[contains(@class,'goods-card') or contains(@class,'product-item')]", 存入列表=product_cards)
    
    输出日志("关键词【" + keyword + "】找到" + 获取列表长度(product_cards) + "个商品")
    
    # ----- 循环采集每个商品的信息 -----
    按列表循环(product_cards, 循环项=card, 循环索引=idx):
        # 捕获元素:商品名称
        
![picture.image](https://p3-volc-community-sign.byteimg.com/tos-cn-i-tlddhu82om/cc8ac70b797c42faa4e7ec1223c688d3~tplv-tlddhu82om-image.image?=&rk3s=8031ce6d&x-expires=1783352702&x-signature=Umh30QyVEqLdFUpD%2FTiJx0PO3P8%3D)
        //div[@class="product-name" or contains(@class,"goods-name")]
        获取元素文本(商品名称, 存入变量=product_name)
        
        # 捕获元素:价格(注意:拼多多显示的是价格区间,如“¥99.00-¥199.00”)
        //span[contains(@class,"price") or contains(@class,"sale-price")]
        获取元素文本(价格元素, 存入变量=price_text)
        
        # 捕获元素:销量
        //span[contains(text(),"已拼") or contains(@class,"sales")]
        获取元素文本(销量元素, 存入变量=sales_text)
        
        # 捕获元素:店铺名
        //a[contains(@class,"store-name") or contains(@class,"shop-name")]
        获取元素文本(店铺名元素, 存入变量=store_name)
        
        # 捕获元素:商品链接
        获取元素属性(商品图片或标题, 属性名="href", 存入变量=product_url)
        
        # 组装一行数据
        新行 = [keyword, product_name, price_text, sales_text, store_name, product_url]
        
        # 追加写入Excel(注意:这里用之前创建的“结果表”)
        追加行数据到表格("C:/data/result.xlsx", 新行)
        
    结束循环
    
    # ----- 判断是否需要翻页 -----
    # 通过判断“下一页”按钮是否存在来决定是否继续
    条件循环(判断元素是否存在("//*[contains(text(),'下一页')]") == True):
        点击元素("//*[contains(text(),'下一页')]")
        等待(3秒)
        # 获取当前页的商品卡片
        获取相似元素列表("//div[contains(@class,'goods-card')]", 存入列表=product_cards)
        按列表循环(product_cards, 循环项=card):
            # 同上采集逻辑...
        结束循环
    结束条件循环
    
结束循环

第三步:价格清洗(核心难点)

拼多多的价格显示是 “¥99.00-¥199.00”“¥99.00起” 的形式,不能直接拿来分析。需要拆成最低价和最高价。

用Python+Pandas清洗(在影刀的“执行Python代码”指令里跑):

import pandas as pd
import re

# 输入:raw_data 从影刀传入(二维列表)
# 输出:cleaned_data 返回影刀

df = pd.DataFrame(raw_data[1:], columns=raw_data[0])
# 列名:['关键词', '商品名', '价格文本', '销量', '店铺名', '链接']

# ===== 价格清洗函数 =====
def extract_price_range(price_str):
    """
    输入:"¥99.00-¥199.00" 或 "¥99.00起" 或 "¥99.00"
    输出:[最低价, 最高价]
    """
    if pd.isna(price_str):
        return [None, None]
    
    text = str(price_str)
    # 提取所有数字(含小数点)
    numbers = re.findall(r'[\d.]+', text)
    if len(numbers) == 0:
        return [None, None]
    
    # 转为浮点数
    nums = [float(n) for n in numbers]
    
    if len(nums) == 1:
        # 只有一个价格:最低价=最高价=该价格
        return [nums[0], nums[0]]
    else:
        # 多个价格:取最小和最大
        return [min(nums), max(nums)]

# 应用清洗
df[['最低价', '最高价']] = df['价格文本'].apply(
    lambda x: pd.Series(extract_price_range(x))
)

# ===== 销量清洗 =====
def clean_sales(text):
    if pd.isna(text):
        return 0
    text = str(text)
    # "10万+" → 100000
    if '万' in text:
        num = re.search(r'[\d.]+', text)
        if num:
            return int(float(num.group()) * 10000)
    # "9999件" → 9999
    num = re.search(r'[\d.]+', text)
    return int(float(num.group())) if num else 0

df['销量_清洗'] = df['销量'].apply(clean_sales)

# ===== 去重:同一商品只保留一条 =====
df = df.drop_duplicates(subset=['商品名'], keep='first')

# ===== 输出 =====
cleaned_data = [df.columns.tolist()] + df.values.tolist()

第四步:翻页的坑与处理方案

拼多多搜索结果页的翻页有个特点:滚动加载而不是传统翻页。在移动端页面上,滑到页面底部会自动加载更多商品。

我的翻页方案(条件循环+滚动):

设置变量(连续无新增次数 = 0)

条件循环(连续无新增次数 < 3):
    # 记录滚动前商品数量
    获取相似元素列表("//div[contains(@class,'goods-card')]", 存入列表=before_cards)
    前数量 = 获取列表长度(before_cards)
    
    # 滚动到页面底部
    滚动到元素("//*[@id='app']/div[last()]")  # 滚动到页面最后
    等待(2秒)  # 等待加载
    
    # 获取滚动后商品数量
    获取相似元素列表("//div[contains(@class,'goods-card')]", 存入列表=after_cards)
    后数量 = 获取列表长度(after_cards)
    
    # 判断有没有新增
    如果 后数量 > 前数量:
        设置变量(连续无新增次数 = 0)
        # 采集新增的商品(只采集新增部分,用索引范围取)
        新增卡片 = after_cards[前数量:后数量]
        按列表循环(新增卡片, 循环项=card):
            # 采集逻辑同上...
        结束循环
    否则:
        设置变量(连续无新增次数 = 连续无新增次数 + 1)
    结束如果
    
结束条件循环

输出日志("滚动加载结束,共采集" + 后数量 + "个商品")

这个方案的优点:

  • 不会无限滚动(连续3次没有新商品就停止)
  • 每次只采集新增的商品,不重复采集
  • 不会因为网络慢而漏数据

防限流策略

拼多多对高频访问有限流,我的经验是:

操作建议间隔原因
每次搜索等待3-5秒搜索结果加载需要时间
每采集一个商品等待0.5-1秒避免被判定为爬虫
每翻一页等待2-3秒页面滚动加载需要时间
每个关键词切换等待5-8秒重置搜索状态

我的限流检测方法: 在关键步骤后加“判断元素是否存在”检测异常页面。

# 检测是否被限流
如果 判断元素是否存在("//*[contains(text(),'验证') or contains(text(),'滑块')]") == True:
    输出日志("检测到验证页面,暂停10秒")
    等待(10秒)
    # 创业版可以接入打码平台,社区版建议手动干预
否则:
    # 正常采集
结束如果

完整流程结构图

开始
  ↓
创建结果Excel(含表头)
  ↓
读取关键词列表
  ↓
打开拼多多移动端 → 检测登录态 → 未登录则登录
  ↓
按列表循环每个关键词 ──────────────┐
  ├→ 输入关键词搜索                    │
  ├→ 等待加载                          │
  ├→ 获取商品卡片列表                  │
  ├→ 循环采集每条商品数据 ──→ 追加写入Excel │
  ├→ 滚动加载翻页(条件循环)           │
  └→ 切换下一个关键词 ────────────────┘
  ↓
所有关键词处理完成
  ↓
执行Python清洗(价格/销量/去重)
  ↓
输出清洗后的Excel
  ↓
结束

常见问题速查

问题原因解决方法
搜索结果为空关键词特殊字符或页面未加载加等待时间,检查关键词是否有特殊符号
价格提取失败价格格式变化(如“¥”变“¥”)用正则提取数字,不依赖固定格式
翻页死循环滚动判断条件设置不当用“连续无新增次数”限制退出
登录态频繁失效Cookie过期每次流程开始重新登录
流程被限流请求频率过高增加等待间隔,设置随机延迟
采集数据量对不上滚动加载时漏采用“增量采集”方案,每次只采新增的

推荐资源

  • 影刀官方《拼多多自动化采集模板》——流程市场里可以直接下载参考
  • 拼多多移动端页面结构更新频率较高,建议每次跑之前手动打开页面确认一下XPath是否还能用

#影刀RPA #RPA自动化 #拼多多 #电商自动化 #批量采集 #数据清洗

作者:林焱

本文为《影刀RPA学习手册》系列文章之一,内容源于实操经验的整理与分享。

0
0
0
0
评论
未登录
暂无评论