Why Automated Price Monitoring Matters
وفي أسواق التجارة الإلكترونية التنافسية، تتغير الأسعار باستمرار. المنافس قد يخفض سعره بخمسة بالمئة في الثانية صباحاً وبحلول الوقت الذي تلاحظ فيه قد خسرت يوم مبيعات رصد الأسعار الآلي يزيل هذه البقعة العمياء عن طريق التتبع المستمر لأسعار المنافسين وتنبيهكم إلى التغيرات في الوقت الحقيقي.
وسواء كنت تُعدّل أسعار البيع بالتجزئة لتظلّ تنافسياً، أو تُقيّم الامتثال للعلامة التجارية (الأسعار المعلن عنها في الألفية)، أو تعقّب اتجاهات السوق، فإن نظاماً جيداً لرصد الأسعار يُدفع لنفسه بسرعة. المكون الرئيسي الذي يجعله يعمل بشكل موثوق به هو بنية تحتية متينة - بدونه، طلبات الرصد الخاصة بك يتم وقفها في غضون ساعات. من أجل نظرة أوسع على جمع بيانات التجارة الإلكترونية، انظر دليل جرد بيانات التجارة الإلكترونية.
هيكل نظام رصد الأسعار
ويوجد في نظام لرصد الأسعار من مستوى الإنتاج أربعة عناصر رئيسية هي: مدير لليوران، ومحرك للخردة، ومخزن للبيانات، وطبقة للإنذار.
| العنصر | المسؤولية | التكنولوجيات |
|---|---|---|
| URL Manager | Stores target URLs, scheduling metadata, and scraping frequency | PostgreSQL, Redis |
| مهندس | صفحات الرسوم من خلال البركات وأسعار المستخرجات | Python/Node.js, ProxyHat, prettySoup/Cheerio |
| تخزين البيانات | تأريخ أسعار المتاجر مع المصابيح | PostgreSQL, TimescaleDB, ClickHouse |
| نظام الإنذار | Detects changes, sends notifications | Webhooks, Slack, Email, SMS |
استراتيجية الجدولة
ولا تحتاج جميع المنتجات إلى نفس تواتر الرصد. وقد تحتاج المواد ذات الأولوية العالية (أفضل 100 وحدة من وحدات التصنيع الخاصة بك، ومنتجات المنافسين المباشرين) إلى فحص على مدار الساعة، في حين يمكن فحص الأصناف ذات الطول يومياً. الأولويات على أساس:
- تقلب الأسعار: وتحتاج المنتجات التي تغير الأسعار في كثير من الأحيان إلى مزيد من الضوابط.
- أثر الإيرادات: أفضل المبيعات الخاصة بك يستحقون أولوية عالية للرصد.
- الكثافة التنافسية: وتحتاج المنافسات التي تضم العديد من المنافسين إلى رصد أكثر صرامة.
وضع تناوب للمتابعة
ويعني رصد الأسعار ضرب نفس اليوران مرارا على مدى أيام وأسابيع وشهور. هذا النمط هو بالضبط ما نُظم مضادة للدبابات مصممة للكشف ولا بد من إقامة شركات ذات تناوب آلي.
ProxyHat Configuration
# Standard rotating proxy (new IP per request)
http://USERNAME:PASSWORD@gate.proxyhat.com:8080
# Geo-targeted for regional pricing (e.g., US prices)
http://USERNAME-country-US:PASSWORD@gate.proxyhat.com:8080
# Session-based for multi-page price checks
http://USERNAME-session-price001:PASSWORD@gate.proxyhat.com:8080وفيما يتعلق برصد الأسعار، يعمل التناوب على كل طلب على أفضل وجه لأن كل عملية تحقق من الأسعار هي عملية مستقلة. الاستخدام المسيرات المستهدفة جغرافيا عند رصد الاختلافات في الأسعار الإقليمية.
Python Implementation
هنا نظام كامل لرصد الأسعار مبني مع (بيثون) (بروكسي هات) (بايتون).
وحدة البرمجيات
import requests
from bs4 import BeautifulSoup
import json
import time
import random
from datetime import datetime
from dataclasses import dataclass, asdict
PROXY_URL = "http://USERNAME:PASSWORD@gate.proxyhat.com:8080"
USER_AGENTS = [
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/124.0.0.0 Safari/537.36",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 Chrome/124.0.0.0 Safari/537.36",
]
@dataclass
class PriceResult:
url: str
price: float | None
currency: str | None
in_stock: bool
scraped_at: str
seller: str | None = None
def scrape_price(url: str, selectors: dict) -> PriceResult:
"""Scrape a product price from any e-commerce site."""
headers = {
"User-Agent": random.choice(USER_AGENTS),
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
"Accept-Language": "en-US,en;q=0.9",
}
proxies = {"http": PROXY_URL, "https": PROXY_URL}
try:
response = requests.get(url, headers=headers, proxies=proxies, timeout=30)
response.raise_for_status()
except requests.RequestException as e:
return PriceResult(
url=url, price=None, currency=None,
in_stock=False, scraped_at=datetime.utcnow().isoformat()
)
soup = BeautifulSoup(response.text, "html.parser")
price = extract_price(soup, selectors.get("price"))
currency = selectors.get("currency", "USD")
in_stock = check_stock(soup, selectors.get("stock"))
return PriceResult(
url=url,
price=price,
currency=currency,
in_stock=in_stock,
scraped_at=datetime.utcnow().isoformat(),
)
def extract_price(soup, selector: str) -> float | None:
"""Extract and parse price from a CSS selector."""
if not selector:
return None
el = soup.select_one(selector)
if not el:
return None
text = el.get_text(strip=True)
# Remove currency symbols, commas, spaces
cleaned = "".join(c for c in text if c.isdigit() or c == ".")
try:
return float(cleaned)
except ValueError:
return None
def check_stock(soup, selector: str) -> bool:
"""Check if product is in stock."""
if not selector:
return True
el = soup.select_one(selector)
if not el:
return False
text = el.get_text(strip=True).lower()
return "in stock" in text or "available" in text
# Site-specific selector configurations
SITE_SELECTORS = {
"amazon.com": {
"price": "span.a-price-whole",
"stock": "#availability span",
"currency": "USD",
},
"walmart.com": {
"price": "[data-testid='price-wrap'] span.f2",
"stock": "[data-testid='fulfillment-badge']",
"currency": "USD",
},
"target.com": {
"price": "[data-test='product-price']",
"stock": "[data-test='fulfillmentSection']",
"currency": "USD",
},
}نظام الرصد
import schedule
import threading
from collections import defaultdict
class PriceMonitor:
def __init__(self, db_connection):
self.db = db_connection
self.price_history = defaultdict(list)
def add_product(self, url: str, site: str, check_interval_minutes: int = 60):
"""Register a product for monitoring."""
selectors = SITE_SELECTORS.get(site, {})
def check():
result = scrape_price(url, selectors)
self.price_history[url].append(result)
self.store_result(result)
self.check_alerts(url, result)
time.sleep(random.uniform(1, 3))
schedule.every(check_interval_minutes).minutes.do(check)
def store_result(self, result: PriceResult):
"""Store price result in database."""
# Insert into price_history table
self.db.execute(
"INSERT INTO price_history (url, price, currency, in_stock, scraped_at) "
"VALUES (%s, %s, %s, %s, %s)",
(result.url, result.price, result.currency,
result.in_stock, result.scraped_at)
)
def check_alerts(self, url: str, result: PriceResult):
"""Check if price change triggers an alert."""
history = self.price_history[url]
if len(history) < 2:
return
prev = history[-2]
curr = history[-1]
if prev.price and curr.price:
change_pct = ((curr.price - prev.price) / prev.price) * 100
if abs(change_pct) >= 5: # 5% threshold
self.send_alert(url, prev.price, curr.price, change_pct)
# Stock status change
if prev.in_stock and not curr.in_stock:
self.send_alert(url, msg="Product went out of stock")
elif not prev.in_stock and curr.in_stock:
self.send_alert(url, msg="Product back in stock")
def send_alert(self, url, old_price=None, new_price=None,
change_pct=None, msg=None):
"""Send price change notification."""
if msg:
print(f"ALERT [{url}]: {msg}")
else:
direction = "dropped" if change_pct < 0 else "increased"
print(f"ALERT [{url}]: Price {direction} {abs(change_pct):.1f}% "
f"(${old_price} -> ${new_price})")
def run(self):
"""Start the monitoring loop."""
while True:
schedule.run_pending()
time.sleep(1)
# Usage
if __name__ == "__main__":
monitor = PriceMonitor(db_connection=None) # Replace with actual DB
# Monitor competitor products
monitor.add_product(
"https://www.amazon.com/dp/B0CHX3QBCH",
site="amazon.com",
check_interval_minutes=60,
)
monitor.add_product(
"https://www.amazon.com/dp/B0D5BKRY4R",
site="amazon.com",
check_interval_minutes=30, # Higher priority
)
monitor.run()Node.js Implementation
من أجل الفرق التي تستخدم (نودج) هنا مُعدّل للرصد باستخدام العميل (س.د.ك).
const axios = require("axios");
const cheerio = require("cheerio");
const { HttpsProxyAgent } = require("https-proxy-agent");
const cron = require("node-cron");
const PROXY_URL = "http://USERNAME:PASSWORD@gate.proxyhat.com:8080";
const agent = new HttpsProxyAgent(PROXY_URL);
const USER_AGENTS = [
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/124.0.0.0 Safari/537.36",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 Chrome/124.0.0.0 Safari/537.36",
];
async function scrapePrice(url, selectors) {
try {
const { data } = await axios.get(url, {
httpsAgent: agent,
headers: {
"User-Agent": USER_AGENTS[Math.floor(Math.random() * USER_AGENTS.length)],
"Accept-Language": "en-US,en;q=0.9",
},
timeout: 30000,
});
const $ = cheerio.load(data);
const priceText = $(selectors.price).first().text().trim();
const price = parseFloat(priceText.replace(/[^0-9.]/g, "")) || null;
return {
url,
price,
currency: selectors.currency || "USD",
inStock: $(selectors.stock).text().toLowerCase().includes("in stock"),
scrapedAt: new Date().toISOString(),
};
} catch (err) {
return { url, price: null, currency: null, inStock: false, scrapedAt: new Date().toISOString() };
}
}
class PriceMonitor {
constructor() {
this.products = [];
this.history = new Map();
}
addProduct(url, selectors, cronExpression = "0 * * * *") {
this.products.push({ url, selectors, cronExpression });
this.history.set(url, []);
cron.schedule(cronExpression, async () => {
const result = await scrapePrice(url, selectors);
const prev = this.history.get(url);
prev.push(result);
if (prev.length >= 2) {
const last = prev[prev.length - 2];
if (last.price && result.price) {
const changePct = ((result.price - last.price) / last.price) * 100;
if (Math.abs(changePct) >= 5) {
console.log(`ALERT [${url}]: Price changed ${changePct.toFixed(1)}%`);
}
}
}
console.log(`Checked ${url}: $${result.price} (${result.inStock ? "in stock" : "out of stock"})`);
});
}
}
// Usage
const monitor = new PriceMonitor();
monitor.addProduct(
"https://www.amazon.com/dp/B0CHX3QBCH",
{ price: "span.a-price-whole", stock: "#availability span", currency: "USD" },
"0 * * * *" // Every hour
);
monitor.addProduct(
"https://www.amazon.com/dp/B0D5BKRY4R",
{ price: "span.a-price-whole", stock: "#availability span", currency: "USD" },
"*/30 * * * *" // Every 30 minutes
);تخزين البيانات وتحليلها
بيانات الأسعار السريعة تصبح قيمة عندما يمكنك تحليل الاتجاهات عبر الزمن
قاعدة البيانات
CREATE TABLE monitored_products (
id SERIAL PRIMARY KEY,
url TEXT NOT NULL,
site VARCHAR(100) NOT NULL,
product_name VARCHAR(500),
our_sku VARCHAR(100),
check_interval_minutes INT DEFAULT 60,
is_active BOOLEAN DEFAULT true,
created_at TIMESTAMPTZ DEFAULT now()
);
CREATE TABLE price_history (
id SERIAL PRIMARY KEY,
product_id INT REFERENCES monitored_products(id),
price DECIMAL(10, 2),
currency VARCHAR(3) DEFAULT 'USD',
in_stock BOOLEAN,
scraped_at TIMESTAMPTZ NOT NULL,
created_at TIMESTAMPTZ DEFAULT now()
);
CREATE INDEX idx_price_history_product_time
ON price_history (product_id, scraped_at DESC);السعر
-- Average daily price for the last 30 days
SELECT
date_trunc('day', scraped_at) AS day,
AVG(price) AS avg_price,
MIN(price) AS min_price,
MAX(price) AS max_price
FROM price_history
WHERE product_id = 1
AND scraped_at >= now() - INTERVAL '30 days'
GROUP BY day
ORDER BY day;
-- Products with price drops > 10% in the last 24 hours
SELECT
mp.product_name,
mp.url,
old_prices.avg_price AS price_yesterday,
new_prices.avg_price AS price_today,
((new_prices.avg_price - old_prices.avg_price) / old_prices.avg_price * 100) AS change_pct
FROM monitored_products mp
JOIN LATERAL (
SELECT AVG(price) AS avg_price
FROM price_history
WHERE product_id = mp.id
AND scraped_at BETWEEN now() - INTERVAL '48 hours' AND now() - INTERVAL '24 hours'
) old_prices ON true
JOIN LATERAL (
SELECT AVG(price) AS avg_price
FROM price_history
WHERE product_id = mp.id
AND scraped_at >= now() - INTERVAL '24 hours'
) new_prices ON true
WHERE ((new_prices.avg_price - old_prices.avg_price) / old_prices.avg_price * 100) < -10;الإشعار والإخطارات
الإنذارات الآلية تضمن ردة فعلك على تغيرات الأسعار بسرعة وتشمل قنوات الإخطار المشتركة ما يلي:
- Slack webhooks: مثالية للظهور على نطاق الفريق إرسال رسائل منظمة مع تفاصيل تغير الأسعار.
- الهضم البريدي: ملخصات يومية أو ساعة لجميع تغيرات الأسعار فوق عتبة
- (ويهوك) جهزوا محرككم للتكرار أو غيره من الأتمتة عندما تتغير الأسعار
- اللوح: تصور اتجاهات الأسعار في الوقت الحقيقي في جميع المنتجات الخاضعة للرصد.
إنذار العاهرات
فرض حدود إنذار مختلفة على سيناريوهات مختلفة:
| السيناريو | Threshold | الإجراء |
|---|---|---|
| انخفاض سعر المنافسة > 5% | 5% | الإخطار المسبق |
| انخفاض أسعار المنافسين | 15% | Email to pricing team + auto-reprice |
| الناتج يخرج من المخزون | تغير الأرصدة | الإنذار بالفرص |
| السعر الوارد أدناه | قيمة خطة العمل الموحدة | إنذار الامتثال |
Proxy Best Practices for Monitoring
ويؤدي الرصد المستمر إلى نشوء تحديات فريدة للإدارة البديلة بالمقارنة مع الخردة لمرة واحدة.
- طلبات التوزيع مع مرور الوقت: بدلاً من التحقق من كل 10000 منتج في منتصف الليل، نشر الشيكات في جميع أنحاء العالم. وهذا يخلق نمطا ثابتا وخفيفا للطلبات.
- استخدام العملاء المقيمين: الهيئات القضائية المقيمة وهي ضرورية للرصد الطويل الأجل لأن نفس مراكز البيانات التي تضرب نفس المواقع اليومية ستُحظر.
- موقع ماتش الجغرافي: وعند رصد التسعير الإقليمي، يُستخدم المحترفون من المنطقة المستهدفة. أي آي بي يُدقّقُ الأسعارَ الألمانية سَيَرى البياناتَ الخاطئةَ أَو يُعاد توجيهها.
- الفشل اليدوي: وإذا فشل طلب ما، فانتظر وأرجع إلى الوراء المفاجئ بدلاً من إعادة الطلب فوراً. راقب معدل نجاحك وقلل من الاتّفاق إذا انخفض
- الخوخ والتدهور: إذا لم يتغير السعر، لا تخزن سجلا مكررا. هذا يبقي قاعدة بياناتك تميل ويجعل التحليل أسرع
المنفذ الرئيسي: رصد الأسعار هو ماراثون، وليس طبعة. تصميم نظامك من أجل أنماط الطلب الثابتة والمستدامة بدلاً من أن تنفجر
Scaling your Monitoring System
بينما ينمو كتالوج منتجاتك يصبح التصعيد بالغ الأهمية هذه هي الأنماط التي تعمل:
- مجمع العمال: Use multiple workers withdraw from a job queue (Redis, RabbitMQ). ولكل عامل صلاته المباشرة ويعمل بشكل مستقل.
- الاستفسارات ذات الأولوية: ويتم فحص المنتجات ذات القيمة العالية أولاً وأكثر تواتراً. وتشغل البنود ذات الأولوية المنخفضة القدرة المتبقية.
- الجدولة الإيجابية: إذا لم يتغير سعر المنتج في 7 أيام، خفض تواتر الشيك تلقائيا. إذا تغير مرتين اليوم، زيادة التردد.
- المعدل الذي يحد من كل موقع: احترموا كل تحديدات الموقع (الأمازون) و (والمارت) و متاجر الـ (نيتش) لديهم تسامحات مختلفة
للمزيد من عمليات الخردة تحقق من دليلنا أفضل عملاء لخردة الإنترنت في عام 2026 واستكشاف خطط تسعير (بروكسي ها) من أجل الرصد العالي الحجم
المداخل الرئيسية
- ويتطلب رصد الأسعار آلياً هيكلاً قوياً: مدير شركة URL، ومحرك الخردة، ومخزن البيانات، ونظام الإنذار.
- فالوكالات المقيمة ذات التناوب في كل طلب ضرورية للرصد المستمر بدون كتل.
- ولا تحتاج جميع المنتجات إلى رصد ساعة.
- تأريخ الأسعار المسروقة في مخطط سهل التوقيت لتحليل الاتجاهات.
- ربطت الحدود القصوى للإنذار لموازنة الاستجابة مع خفض الضوضاء.
- طلبات التوزيع بالتساوي مع مرور الوقت من أجل نمط مستدام من الخردة منخفض الاحتمال.
مستعد لبناء نظام رصد الأسعار الخاص بك؟ ابدأ وكيلات النيابة السكنية ونقرأ دليل خردة التجارة الإلكترونية من أجل الاستراتيجية الكاملة وللاطلاع على تفاصيل التنفيذ التقني، انظر أدلةنا بشأن (بإستعمال المحترفين في (بيثون و (بإستعمال المحترفين في (نودج.






