TL;DR
一个 Etsy 商品数据集应代表您打算比较的商品及其特定的报价或变体。仅包含标题和浮点价格的文件可能足以用于粗略库存,但不足以进行可靠的价格监控。您需要标识、货币、观察时间以及足够的变体上下文来解释变化。
对于自营店铺集成,从 Etsy 提供的所需操作源开始。对于更广泛的研究项目,在收集数据前验证允许的访问权限和使用情况。公开的商品页面并不能证明每种自动收集方法都是允许的。浏览器环境管理执行;它不会扩展应用的访问级别。
根据项目实际有权使用的字段和范围选择数据路径。结构化数据可以减少解析歧义,但仍需要模式验证和适当的授权模型。在允许的情况下,浏览器审查对于解决特定差异很有用,而不是取代所有结构化集成。
Etsy 的 认证指南 记录了用于范围操作的 API 密钥和 OAuth 要求。当前指南指定了由冒号分隔的 keystring 和共享密钥组成的 x-api-key 值。在实现时请验证官方参考中的当前要求;旧教程可能显示不兼容的标题格式。
仅请求实际端点所需的范围。只读商品摄入请求不应因示例中包含而请求写入或删除权限。将令牌和应用密钥保留在文章代码、日志和导出数据之外。本文未运行任何经过认证的 Etsy API 请求。
官方 商品教程 描述了生命周期状态和库存变体。商品可能处于非活动状态或售罄,而收集者也可能无法检索到它。请分别保留这些可能性。部分结果页面中的缺失记录不足以证明卖家删除了商品。
对于授权店铺工作流,在将差异视为解析器缺陷之前,比较所选变体、数量、货币和观察时间。记录浏览器实际显示的内容。不要将类别卡片起始价格、配置的变体价格和最终结账总额等同起来。
使用一个商品表来存储商品级标识,当源提供该详细信息时使用一个报价或变体表。将原始标识符存储为文本以避免电子表格转换问题。保留源中产品、报价和变体属性之间的关系,而不是将不相关的选项扁平化为单个标题字符串。
| 观察 | 必要的上下文 | 常见的误解 |
|---|---|---|
| 商品价格 | 货币、时间、价格含义 | 将其视为每个变体的价格 |
| 变体报价 | 所选属性和标识符 | 将不同尺寸的比较视为价格变化 |
| 数量 | 范围和源状态 | 将商品级数字称为通用库存 |
| 缺失行 | 分页和运行完整性 | 在批量失败后报告删除 |
使您的比较键显式化。例如,价格历史记录可能按 listing_id、变体签名、货币和观察时间进行键控。这是一个建议的仓库设计,而不是 Etsy 返回名为 variation_signature 字段的声明。区分您的归一化列与提供方字段。
Etsy 的 金额定义 描述了金额除以除数和单独的货币代码。硬编码的除以 100 会破坏除数不同的记录。当值用于对账时,二进制浮点算术也会引入可避免的表示问题。
此 Python 示例使用围绕这些记录字段构建的合成金额对象。它验证除数并保留货币。这是一个转换测试,而不是从真实店铺捕获的 API 响应。
from decimal import Decimal
import json
def money(value):
amount, divisor = value["amount"], value["divisor"]
if type(amount) is not int or type(divisor) is not int or divisor <= 0:
raise ValueError("integer amount and positive integer divisor required")
currency = value["currency_code"]
if not isinstance(currency, str) or len(currency) != 3 or not currency.isalpha():
raise ValueError("three-letter currency code required")
return {"value": format(Decimal(amount) / Decimal(divisor), "f"),
"currency": currency.upper()}
samples = [{"amount": 1299, "divisor": 100, "currency_code": "USD"},
{"amount": 2500, "divisor": 1000, "currency_code": "USD"}]
result = [money(x) for x in samples]
assert result[0]["value"] == "12.99"
assert result[1]["value"] == "2.5"
try:
money({"amount": 1, "divisor": 0, "currency_code": "USD"})
except ValueError:
rejected_zero_divisor = True
else:
raise AssertionError("zero divisor was accepted")
print(json.dumps({"converted": result, "rejected_zero_divisor": rejected_zero_divisor}))
执行的本地测试返回了 12.99 和 2.5 美元,并拒绝了零除数。第二个测试用例故意使用不同的除数以暴露常见的实现假设。三字母代码的验证仅是格式检查;生产环境的货币政策应使用集成支持的货币集。不要在定义报告的会计政策之前静默转换货币或四舍五入值。
从有限的授权店铺或商品集开始。存储原始响应及其操作、时间和脱敏诊断上下文。在验证所需标识符和价格结构后,再对每个商品进行归一化。将页面或游标完成单独跟踪,而不是记录返回的行数。
对于重复运行,插入当前表示并在项目需要时追加历史价格观察。对接受的行、拒绝的行和重复的标识符进行对账。如果页面失败,请标记运行为部分完成,并根据端点的当前指南重试。在完整比较和预期删除策略支持之前,不要标记未见过的商品为已删除。
Nstbrowser 可以围绕为预期店铺工作流保存的配置文件组织浏览器检查。当需要将结构化记录与允许的页面视图进行比较时,这很有用。组设置可帮助您审查环境的存储和同步选择。当 RPA 的范围已授权且输出已检查时,它可以支持有限的审查序列。这些功能不会取代 Etsy 应用审批、API 认证或正确的变体级数据模型。
使用 配置文件创建 准备环境,检查 组设置,并从 RPA 文档 中适应允许的序列。将已知商品和所选变体与结构化记录进行比较。此处未执行任何实时 Etsy 浏览器或 Nstbrowser 集成。
使用试点验证含义,而不仅仅是成功提取。只有当其他审查者可以确定该行代表哪个商品、变体、货币和时间点时,该行才有用。
问:Etsy 价格始终是金额除以 100 吗?
不。请使用返回的除数以及金额和货币代码。
问:API 密钥是否授予所有操作的访问权限?
不。端点范围、OAuth 授权、应用访问和允许的使用仍然重要。
问:一个商品价格能否代表所有变体?
不要假设。请保留比较所用的特定报价或变体上下文。
问:一次运行中缺失的商品是否证明它已被删除?
不。部分收集、访问问题或提取失败也可能导致缺失记录。