抖音电商(抖音小店)的体量越来越大,采集商品数据用于选品、竞品分析、价格监控成了刚需。但抖音网页版(shop.douyin.com)反爬策略比淘宝更严,且页面大量使用异步加载。
完整采集方案: 登录抖音小店或抖音商城 → 搜索关键词 → 滚动加载商品列表 → 采集商品标题、价格、销量、店铺名 → 进入商品详情页采集佣金、评价数 → 存入Excel。同时支持采集某个店铺的所有商品。
⚠️ 注意:抖音网页版反爬较强,建议使用已登录的Cookie、指纹浏览器(参考选题“浏览器指纹与反反爬”),并控制采集频率。
第一步:捕获抖音商品页面的关键元素
以抖音商城(https://haohuo.jinritemai.com)或抖音APP的网页版商品搜索页为例:
# 搜索页 ====================================

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

# 2. 搜索按钮
//button[@type='submit']
# 3. 商品卡片容器
//div[contains(@class,'product-card')] | //div[contains(@class,'goods-card')]

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

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

# 7. 销量(格式“已售1.2万”)
.//div[contains(@class,'sales')] | .//span[contains(@class,'sold')]
# 8. 店铺名称
.//div[contains(@class,'shop')]//span | .//a[contains(@class,'shop-name')]


# 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匹配固定的英文关键词(如product、price、sold),不要依赖完整的class名。
第二步:登录与保持会话
抖音网页版未登录能看一部分商品,但有限制。建议用Cookie保持登录态。
A_登录抖音子流程(复用Cookie):
流程参数:
- 输出:是否成功
# 打开抖音商城首页
打开网页("https://haohuo.jinritemai.com")
等待元素出现("搜索框", 超时=10)
# 检查是否已登录(通过是否存在“我的订单”或头像判断)
Try:
判断元素是否存在("//div[contains(@class,'user-avatar')]", 超时=2)
如果存在:
输出日志("已登录,无需重复登录")
返回 True
Catch:
输出日志("未登录,尝试加载Cookie")


# 从全局变量或文件读取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秒 |
反爬策略强化
抖音电商的风控比淘宝松一些,但以下措施能显著提高稳定性:
- 使用登录Cookie:未登录状态下连续访问几十次就会出验证
- 随机等待:每次HTTP请求间隔1-3秒随机值
- 模拟人类滚动:不要一次性滚动5000像素,分多次小距离滚动
- 限制采集量:单个关键词不超过100个商品
- 避开高峰期:凌晨1-6点采集成功率更高
推荐资源
- 抖音电商学习中心:https://school.jinritemai.com
- 影刀官方社区搜索“抖音商品”,有部分采集模板
- 比特指纹浏览器(免费版3个环境),配合抖音采集使用
我的经验:抖音商品采集的难点不在技术,而在反爬。建议用比特指纹浏览器+静态住宅代理+随机延迟,一个账号每天采集不超过500个商品,基本稳定。社区版用户优先采集搜索页,不进详情页,30分钟能跑300个商品左右。
作者:林焱
本文为《影刀RPA学习手册》系列文章之《抖音商品采集与店铺数据分析》,内容源于实操经验的整理与分享。
