可视化 eBay 竞争对手定价:从原始 JSONL 到价格趋势仪表盘
Source: Dev.to
在竞争激烈的电子商务领域,价格往往是唯一决定客户是点击你商品的 “Buy It Now” 还是竞争对手商品的因素。抓取数据只是第一步——真正的价值在于将原始数据转化为可操作的洞察:实时发现被压价、识别价格底线,以及跟踪随时间的趋势。
本指南展示了如何构建一个端到端的流水线,以实现:
- 抓取 eBay 商品数据,使用 Playwright。
- 处理 数据,使用 Pandas。
- 可视化 竞争对手的价格变动,在 Streamlit 仪表盘中。
1. 设置
我们将使用 Ebay.com‑Scrapers 仓库,其中包含针对 eBay 结构优化的生产就绪爬虫。
前置条件
- Python 3.8+
- 一个 ScrapeOps API Key(用于绕过反机器人)——获取方式请参见
- 基本的终端操作技能
安装
# Clone the repo
git clone https://github.com/scraper-bank/Ebay.com-Scrapers.git
cd Ebay.com-Scrapers/python/playwright/product_data
# Install dependencies
pip install playwright playwright-stealth pandas streamlit
# Install the Chromium browser used by Playwright
playwright install chromium
我们使用 playwright/product_data 实现,因为它可以提取诸如 productId、price、availability 等细粒度信息,这对于时间序列跟踪至关重要。
2. 配置竞争对手的爬虫
默认的爬虫只处理单个 URL。若要跟踪竞争对手,需要定期对 产品页面列表 运行爬虫。
创建一个名为 run_tracker.py 的包装脚本,循环遍历目标 URL 并保存结果。爬虫会自动在文件名后追加时间戳(例如 ebay_com_product_page_scraper_data_20260116_090000.jsonl),从而便于进行历史追踪。
# run_tracker.py
import asyncio
from scraper.ebay_com_scraper_product_v1 import extract_data, API_KEY
from playwright.async_api import async_playwright
# List of competitor product URLs to monitor
COMPETITOR_URLS = [
"https://www.ebay.com/itm/123456789012",
"https://www.ebay.com/itm/987654321098",
]
async def run_monitoring_session():
async with async_playwright() as p:
browser = await p.chromium.launch(headless=True)
page = await browser.new_page()
for url in COMPETITOR_URLS:
print(f"Scraping competitor: {url}")
await page.goto(url)
data = await extract_data(page)
# Data saving is handled by the DataPipeline class in the core scraper
print(f"Extracted Price: {data.price} {data.currency}")
await browser.close()
if __name__ == "__main__":
asyncio.run(run_monitoring_session())
3. 理解数据结构
爬虫会输出 JSONL(JSON Lines) 文件——一种可流式处理的格式,对大规模价格跟踪数据集来说内存使用更高效。
示例记录
{
"productId": "123456789012",
"name": "Apple iPhone 15 Pro - 128GB - Blue Titanium",
"price": 899.0,
"currency": "USD",
"availability": "in_stock",
"seller": { "name": "TopTierElectronics", "rating": 99.8 }
}
关键细节
- 价格清洗 – 爬虫会将类似
"$899.00"的字符串转换为浮点数 (899.0)。 - 可用性 – 当竞争对手出现
out_of_stock时,需要决定在图表上如何表示(例如,断开折线或绘制为零)。
4. 使用 Pandas 进行数据摄取与清洗
每次爬虫运行都会生成一个新文件。第一步是将所有文件合并为一个按时间顺序排列的 DataFrame。我们从文件名中提取时间戳,以构建时间轴。
import pandas as pd
import glob
import re
import json
from datetime import datetime
def load_historical_data(directory="./"):
"""Load all JSONL files generated by the scraper into a single DataFrame."""
all_data = []
# Find all JSONL files matching the scraper’s naming pattern
files = glob.glob(f"{directory}/ebay_com_product_page_scraper_data_*.jsonl")
for file in files:
# Extract timestamp from filename: e.g., 20260116_090000
match = re.search(r'(\d{8}_\d{6})', file)
if not match:
continue
timestamp = datetime.strptime(match.group(1), "%Y%m%d_%H%M%S")
with open(file, "r", encoding="utf-8") as f:
for line in f:
item = json.loads(line)
item["scrape_timestamp"] = timestamp
all_data.append(item)
df = pd.DataFrame(all_data)
# Ensure price is numeric
df["price"] = pd.to_numeric(df["price"], errors="coerce")
return df
Source: …
5. 使用 Streamlit 构建仪表盘
现在我们创建一个可视化界面,让你可以按产品名称筛选,并查看价格在天或周之间的波动。
dashboard.py
import streamlit as st
import pandas as pd
# Load the helper function from the previous section
from load_data import load_historical_data # adjust import path as needed
st.set_page_config(page_title="eBay Price Tracker", layout="wide")
st.title("📈 eBay Competitor Price Trends")
# Load data
df = load_historical_data()
# Sidebar filters
available_products = df["name"].unique()
selected_products = st.sidebar.multiselect(
"Select Products to Track",
options=available_products,
default=available_products[:2],
)
filtered_df = df[df["name"].isin(selected_products)]
# Main chart
if not filtered_df.empty:
# Pivot data so each product has its own time series
pivot = (
filtered_df.pivot_table(
index="scrape_timestamp",
columns="name",
values="price",
aggfunc="first",
)
.sort_index()
)
st.line_chart(pivot)
else:
st.info("No data available for the selected products.")
运行仪表盘:
streamlit run dashboard.py
现在你将拥有一个交互式仪表盘,它:
- 显示任意选中竞争对手产品的价格趋势。
- 当新的 JSONL 文件出现时自动更新(只需刷新页面)。
- 通过折线图中的间断突出显示缺货期间。
额外的价格历史图(可选)
# each product has its own column for the line chart
chart_data = filtered_df.pivot(
index='scrape_timestamp',
columns='name',
values='price'
)
st.subheader("Price History")
st.line_chart(chart_data)
# Metrics
cols = st.columns(len(selected_products))
for i, product in enumerate(selected_products):
latest_price = filtered_df[filtered_df['name'] == product].iloc[-1]['price']
cols[i].metric(label=product[:30] + "...", value=f"${latest_price}")
else:
st.write("Please select a product to see the price trend.")
使用以下命令运行仪表盘:
streamlit run dashboard.py
6. 自动化工作流
仪表板只有在数据是最新的情况下才有价值。每天早上手动运行爬虫效率低下。
Linux / macOS
设置 cron 任务 每 6 小时运行一次 run_tracker.py 脚本:
0 */6 * * * /usr/bin/python3 /path/to/run_tracker.py
Windows
使用 任务计划程序 实现相同的效果。完成自动化后,Streamlit 仪表板将在每次刷新页面时更新为最新的价格数据。
总结
我们已经从简单的数据提取转向构建一个功能性业务工具。通过将 ScrapeOps eBay 仓库的抓取能力与 Pandas 和 Streamlit 的分析能力相结合,您现在拥有了一个自定义的价格情报平台。
关键要点
- JSONL 高效 – 记录时间序列抓取数据的最佳格式。
- 文件名时间戳 – 将元数据存储在文件名中,可防止内部 JSON 结构更改时的数据丢失。
- 可视化有效 – 在折线图上看到 5 % 的价格下降,比扫描原始文本文件更容易采取行动。
想了解更多关于绕过反机器人措施的内容,请查看 eBay Scraping Breakdown。