文档备案控制台
免费开始使用

影刀RPA进阶教程:抖音商品采集与店铺数据分析——搜索/店铺商品/详情页

抖音电商(抖音小店)的体量越来越大,采集商品数据用于选品、竞品分析、价格监控成了刚需。但抖音网页版(shop.douyin.com)反爬策略比淘宝更严,且页面大量使用异步加载。

完整采集方案: 登录抖音小店或抖音商城 → 搜索关键词 → 滚动加载商品列表 → 采集商品标题、价格、销量、店铺名 → 进入商品详情页采集佣金、评价数 → 存入Excel。同时支持采集某个店铺的所有商品。

⚠️ 注意:抖音网页版反爬较强,建议使用已登录的Cookie、指纹浏览器(参考选题“浏览器指纹与反反爬”),并控制采集频率。


第一步:捕获抖音商品页面的关键元素

picture.image

以抖音商城(https://haohuo.jinritemai.com)或抖音APP的网页版商品搜索页为例:

# 搜索页 ====================================

![picture.image](https://p6-volc-community-sign.byteimg.com/tos-cn-i-tlddhu82om/5188e24dc6bf4beaadf026adbbd8dee0~tplv-tlddhu82om-image.image?=&rk3s=8031ce6d&x-expires=1782610847&x-signature=Uj2u0xA%2F%2FHcCXegCSWonO9bgj4M%3D)

# 1. 搜索框
//input[@placeholder='搜索商品' or contains(@class,'search')]


![picture.image](https://p6-volc-community-sign.byteimg.com/tos-cn-i-tlddhu82om/62e57cb0be164a5f9636fca3a4f64857~tplv-tlddhu82om-image.image?=&rk3s=8031ce6d&x-expires=1782610847&x-signature=w4S7dYapzZ%2BXtkY46sDDtQCsyHo%3D)
# 2. 搜索按钮
//button[@type='submit']

# 3. 商品卡片容器
//div[contains(@class,'product-card')] | //div[contains(@class,'goods-card')]

![picture.image](https://p6-volc-community-sign.byteimg.com/tos-cn-i-tlddhu82om/3687f5b3f5ff47d68c8ef04f72be4413~tplv-tlddhu82om-image.image?=&rk3s=8031ce6d&x-expires=1782610847&x-signature=avbdYW4JHVS1rm72IWPzmv4MVL4%3D)

# 4. 商品标题(相对于卡片)
.//div[contains(@class,'title')] | .//a[contains(@class,'title')]

# 5. 商品链接(相对于卡片)

![picture.image](https://p6-volc-community-sign.byteimg.com/tos-cn-i-tlddhu82om/d9057f5b62e7404590340e213963e27e~tplv-tlddhu82om-image.image?=&rk3s=8031ce6d&x-expires=1782610847&x-signature=5EsYOxuJ6Qhb3xmjy641MjacjTU%3D)
.//a[contains(@class,'title')]/@href | .//a[contains(@class,'product')]/@href

# 6. 价格(格式“¥19.9”)
.//div[contains(@class,'price')]//span | .//span[contains(@class,'current-price')]


![picture.image](https://p6-volc-community-sign.byteimg.com/tos-cn-i-tlddhu82om/a9878eece4024c0face2bfab180605a8~tplv-tlddhu82om-image.image?=&rk3s=8031ce6d&x-expires=1782610847&x-signature=xVYSpeX%2BYOWWu4gILBj58f7US%2F8%3D)
# 7. 销量(格式“已售1.2万”)
.//div[contains(@class,'sales')] | .//span[contains(@class,'sold')]

# 8. 店铺名称
.//div[contains(@class,'shop')]//span | .//a[contains(@class,'shop-name')]

![picture.image](https://p6-volc-community-sign.byteimg.com/tos-cn-i-tlddhu82om/0c9f7b11389048748c151653ff1a2430~tplv-tlddhu82om-image.image?=&rk3s=8031ce6d&x-expires=1782610847&x-signature=w2t3KR4kIKbLhzYrqH%2FIFlFKC2s%3D)

![picture.image](https://p6-volc-community-sign.byteimg.com/tos-cn-i-tlddhu82om/2723c687ffcf490c94d994782ab63341~tplv-tlddhu82om-image.image?=&rk3s=8031ce6d&x-expires=1782610847&x-signature=daT3aZNChlEQ9%2B79PHeRIUFAk1s%3D)
# 9. 商品图片
.//img[contains(@class,'img')]/@src

# 筛选栏 ====================================

# 10. 销量排序
//div[contains(@class,'sort')]//span[contains(text(),'销量')]

# 11. 价格区间筛选框(如有)
//input[@placeholder='最低价']

# 详情页 ====================================

# 12. 详情页标题
//h1[contains(@class,'title')]

# 13. 详情页价格
//div[contains(@class,'price')]//span[contains(@class,'current')]

# 14. 评价数量(“全部评价”旁边的数字)
//div[contains(@class,'comment-count')] | //span[contains(@class,'rate-count')]

# 15. 商品参数(品牌、品类)

//div[contains(@class,'parameter')]//span

⚠️ 注意:抖音电商页面改版频繁,建议用contains匹配固定的英文关键词(如productpricesold),不要依赖完整的class名。


第二步:登录与保持会话

抖音网页版未登录能看一部分商品,但有限制。建议用Cookie保持登录态。

A_登录抖音子流程(复用Cookie):

流程参数:
  - 输出:是否成功

# 打开抖音商城首页
打开网页("https://haohuo.jinritemai.com")
等待元素出现("搜索框", 超时=10)

# 检查是否已登录(通过是否存在“我的订单”或头像判断)
Try:
    判断元素是否存在("//div[contains(@class,'user-avatar')]", 超时=2)
    如果存在:
        输出日志("已登录,无需重复登录")
        返回 True
Catch:
    输出日志("未登录,尝试加载Cookie")

![picture.image](https://p6-volc-community-sign.byteimg.com/tos-cn-i-tlddhu82om/619c1475c3b44fee984318e5118ea46b~tplv-tlddhu82om-image.image?=&rk3s=8031ce6d&x-expires=1782610847&x-signature=6l9Buox14KF%2BEVWtateTqzo57as%3D)

![picture.image](https://p6-volc-community-sign.byteimg.com/tos-cn-i-tlddhu82om/ad02313e365f4db1be8d11b7ca2029d1~tplv-tlddhu82om-image.image?=&rk3s=8031ce6d&x-expires=1782610847&x-signature=eR7NRHhtS%2B0IHMFR87tIDlVTXew%3D)
# 从全局变量或文件读取Cookie
${cookie} = 读取文件内容("D:\\douyin_cookie.txt")
如果 ${cookie} != "":
    设置Cookie(${cookie})
    刷新网页()
    固定等待(2)

# 再次验证
判断元素是否存在("//div[contains(@class,'user-avatar')]") → ${已登录}
如果 ${已登录}:
    返回 True
否则:
    输出日志("Cookie失效,需手动登录")
    返回 False

首次登录需要手动完成,然后通过“获取Cookie”指令保存到文件。


第三步:搜索并采集商品列表

C_搜索抖音商品子流程:

流程参数:
  - 输入:关键词、最大数量(默认100)
  - 输出:商品列表

输出日志("【抖音商品搜索】关键词:" + ${关键词})

# 进入抖音商城搜索页
打开网页("https://haohuo.jinritemai.com")
等待元素出现("搜索框", 超时=8)

输入文本("搜索框", ${关键词}, 模式="模拟输入")
固定等待(0.5)
点击元素("搜索按钮")
等待元素出现("商品卡片容器", 超时=10)

# 可选:点击“销量排序”
Try:
    点击元素("销量排序按钮")
    固定等待(1)
Catch:
    输出日志("无法点击销量排序")

# 滚动加载(抖音是无限滚动)
${商品列表} = 调用子流程(C_滚动加载抖音, 输入=${最大数量})

# 采集数据
${结果} = 调用子流程(C_解析抖音卡片, 输入=${商品列表})

输出日志("共采集到${结果长度}个商品")
返回 ${结果}

C_滚动加载抖音子流程:

流程参数:
  - 输入:目标数量
  - 输出:所有卡片元素列表

${所有卡片} = 创建空列表()
${上次数量} = 0
${连续无新增} = 0

条件循环(${所有卡片}.长度 < ${目标数量}${连续无新增} < 3):
    获取相似元素列表("商品卡片容器") → ${当前卡片列表}
    
    # 合并新卡片(去重,通过商品链接)
    元素列表循环(${当前卡片列表}):
        ${当前卡片} = 当前元素
        # 取卡片中的商品链接作为唯一标识
        Try:
            相对于元素(${当前卡片}) → 捕获链接元素
            ${链接} = 获取属性(链接元素, "href")
            # 如果链接不在已有列表中,添加卡片
            如果 ${所有卡片}.长度 == 0 或 链接 不在 ${已收集链接}:
                添加元素到列表(${所有卡片}, ${当前卡片})
                添加元素到列表(${已收集链接}, ${链接})
        Catch:
            # 无法获取链接,直接用卡片对象判断(不推荐)
            添加元素到列表(${所有卡片}, ${当前卡片})
    
    ${当前总数} = ${所有卡片}.长度
    
    如果 ${当前总数} > ${上次数量}:
        ${上次数量} = ${当前总数}
        ${连续无新增} = 0
    否则:
        ${连续无新增} = ${连续无新增} + 1
    
    # 滚动到底部
    滚动页面(方向=向下, 距离=800)
    调用子流程(D_随机等待, 输入=1.5)

返回 ${所有卡片}

C_解析抖音卡片子流程:

流程参数:
  - 输入:卡片元素列表
  - 输出:二维列表

${结果} = 创建空列表()

元素列表循环(${卡片列表}):
    ${当前卡片} = 当前元素
    
    # 标题
    Try:
        相对于元素(${当前卡片}) → 捕获标题元素
        ${标题} = 获取文本(标题元素)
        ${标题} = 去除首尾空格(${标题})
    Catch:
        ${标题} = ""
    
    # 链接
    Try:
        相对于元素(${当前卡片}) → 捕获链接元素
        ${链接} = 获取属性(链接元素, "href")
        如果 字符串包含(${链接}, "//"):
            ${链接} = "https:" + ${链接}
        else:
            ${链接} = "https://haohuo.jinritemai.com" + ${链接}
    Catch:
        ${链接} = ""
    
    # 价格
    Try:
        相对于元素(${当前卡片}) → 捕获价格元素
        ${价格文本} = 获取文本(价格元素)
        ${价格} = 调用子流程(D_清洗价格, 输入=${价格文本})
    Catch:
        ${价格} = 0
    
    # 销量
    Try:
        相对于元素(${当前卡片}) → 捕获销量元素
        ${销量文本} = 获取文本(销量元素)
        ${销量} = 调用子流程(D_清洗销量, 输入=${销量文本})
    Catch:
        ${销量} = 0
    
    # 店铺
    Try:
        相对于元素(${当前卡片}) → 捕获店铺元素
        ${店铺} = 获取文本(店铺元素)
    Catch:
        ${店铺} = ""
    
    添加元素到列表(${结果}, [${标题}, ${价格}, ${销量}, ${店铺}, ${链接}])

返回 ${结果}

第四步:采集商品详情页(评价、参数)

详情页有更丰富的数据,但每个商品都进去会大幅增加耗时。建议只对前N个商品或特定商品采集。

C_抖音详情页子流程:

流程参数:
  - 输入:商品URL
  - 输出:评价数、好评率、商品参数(品牌等)

输出日志("进入详情页:" + ${商品URL})

打开网页(${商品URL}, 方式="新建标签页")
等待元素出现("详情页标题", 超时=10)

# 评价数
Try:
    获取文本("//div[contains(@class,'comment-count')] | //span[contains(@class,'rate-count')]") → ${评价文本}
    ${评价数} = 调用子流程(D_提取数字, 输入=${评价文本})
Catch:
    ${评价数} = 0

# 好评率(可能显示为“98%”)
Try:
    获取文本("//div[contains(@class,'good-rate')] | //span[contains(@class,'rate')]") → ${好评文本}
    ${好评率} = 调用子流程(D_提取数字, 输入=${好评文本})
Catch:
    ${好评率} = 0

# 商品参数(品牌、品类)
Try:
    获取文本("//div[contains(@class,'parameter')]//span[contains(text(),'品牌')]/following-sibling::span") → ${品牌}
Catch:
    ${品牌} = ""

关闭标签页()
返回 [${评价数}, ${好评率}, ${品牌}]

第五步:采集店铺内所有商品

有时候你想分析一个店铺的全部商品(如竞品店铺)。

C_采集店铺商品子流程:

流程参数:
  - 输入:店铺主页URL
  - 输出:商品列表

# 打开店铺主页
打开网页(${店铺URL})
等待元素出现("商品卡片容器", 超时=10)

# 滚动加载(店铺商品页也是无限滚动)
${所有卡片} = 调用子流程(C_滚动加载抖音, 输入=999)

# 解析卡片
${结果} = 调用子流程(C_解析抖音卡片, 输入=${所有卡片})

返回 ${结果}

店铺主页URL格式示例:https://haohuo.jinritemai.com/shop/xxxxx


第六步:主流程(批量关键词)

B_抖音采集主流程

# 1. 初始化
输出日志("开始抖音商品采集")
调用子流程(A_登录抖音) → ${登录成功}
如果 ${登录成功} == False:
    停止流程()

# 2. 读取关键词(Excel第一列)
打开Excel("抖音关键词.xlsx")
读取列数据到列表(列="A", 起始行=2) → ${关键词列表}
关闭Excel()

# 3. 创建结果文件
打开Excel("抖音采集结果_" + 当前日期() + ".xlsx")
追加行到表格(["关键词", "标题", "价格", "销量", "店铺", "评价数", "好评率", "链接"])

# 4. 循环关键词
列表循环(${关键词列表}):
    ${关键词} = 当前项
    
    调用子流程(C_搜索抖音商品, 输入=[${关键词}, 50]) → ${商品列表}
    
    # 可选:采集前10个商品的详情页
    ${增强列表} = 创建空列表()
    ${索引} = 0
    列表循环(${商品列表}):
        ${一行} = 当前项
        ${链接} = ${一行}[4]
        
        如果 ${索引} < 10:
            调用子流程(C_抖音详情页, 输入=${链接}) → [${评价数}, ${好评率}, ${品牌}]
            一行增强 = [${关键词}] + ${一行} + [${评价数}, ${好评率}, ${链接}]
        否则:
            一行增强 = [${关键词}] + ${一行} + ["", "", ${链接}]
        
        添加元素到列表(${增强列表}, 一行增强)
        ${索引} = ${索引} + 1
        调用子流程(D_随机等待, 输入=1)
    
    # 写入Excel
    列表循环(${增强列表}):
        追加行到表格(当前项)
    
    # 关键词间隔
    调用子流程(D_随机等待, 输入=5)

关闭Excel()
输出日志("全部完成")

数据清洗函数

D_清洗价格(Python):

import re
price_str = input_data.get('price', '')
match = re.search(r'[\d.]+', price_str)
if match:
    result = float(match.group())
else:
    result = 0.0

D_清洗销量(Python):

import re
sales_str = input_data.get('sales', '')
# 格式:"已售1.2万" -> 12000, "已售1234" -> 1234
match = re.search(r'(\d+(?:\.\d+)?)\s*万', sales_str)
if match:
    result = int(float(match.group(1)) * 10000)
else:
    match = re.search(r'(\d+)', sales_str)
    result = int(match.group(1)) if match else 0

常见问题速查

问题原因解决方法
搜索后没有商品未登录或反爬使用Cookie登录;加随机延迟;换指纹浏览器
滚动加载不到更多商品页面只加载60个左右设置最大滚动8-10次,超过就停止
销量显示“--”销量数据被隐藏部分商品不显示销量,用0代替
详情页评价数获取失败页面结构不同多XPath备选;从商品卡片直接采(如果有)
采集到重复商品滚动合并时未去重用商品链接作为唯一标识
触发滑块验证码频率过高每个商品间隔2-3秒,关键词间隔5-8秒

反爬策略强化

抖音电商的风控比淘宝松一些,但以下措施能显著提高稳定性:

  1. 使用登录Cookie:未登录状态下连续访问几十次就会出验证
  2. 随机等待:每次HTTP请求间隔1-3秒随机值
  3. 模拟人类滚动:不要一次性滚动5000像素,分多次小距离滚动
  4. 限制采集量:单个关键词不超过100个商品
  5. 避开高峰期:凌晨1-6点采集成功率更高

推荐资源

  • 抖音电商学习中心:https://school.jinritemai.com
  • 影刀官方社区搜索“抖音商品”,有部分采集模板
  • 比特指纹浏览器(免费版3个环境),配合抖音采集使用

我的经验:抖音商品采集的难点不在技术,而在反爬。建议用比特指纹浏览器+静态住宅代理+随机延迟,一个账号每天采集不超过500个商品,基本稳定。社区版用户优先采集搜索页,不进详情页,30分钟能跑300个商品左右。


作者:林焱

本文为《影刀RPA学习手册》系列文章之《抖音商品采集与店铺数据分析》,内容源于实操经验的整理与分享。

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