跳到正文
DEV Community· Gio Rich·· 4 小時前AI 評分39

如何以 JSON 取得 Amazon 各類別及市場的完整百大暢銷榜

How to get Amazon's full Best Sellers top 100 for any category and marketplace as JSON

AI 導讀

Amazon Best Sellers Scraper 是 Apify 上的付費工具,提供免費試用額度,可抓取各市場、各類別每小時更新的完整百大暢銷商品資料,並以 JSON 輸出。它透過 HTTP 和住宅代理擷取每頁 50 件商品及子類別資料,支援 Python 和 Node。每份榜單抓取 100 件商品需 $0.15;追蹤 20 個類別每月約需 $3。

正文

I built this actor; it's a paid tool on Apify with a free trial credit.

Amazon's Best Sellers pages are the simplest public signal of what's selling: a top 100 per category, per marketplace, refreshed hourly. They're also annoying to collect. Each page only renders 30 of its 50 products and loads the other 20 when you scroll, the two pages live behind a pg= parameter, prices come in a different format on every marketplace, and Amazon blocks most datacenter IPs after a few requests.

I'm an 18-year-old engineering student, and I wrapped all of that in an actor called Amazon Best Sellers Scraper. This post shows how to call it from Python and Node, what the data looks like, and one small project: a daily rank tracker for a category.

How it works, briefly

An Amazon list page embeds all 50 ASINs of the page with their ranks in a data attribute and renders the first 30 product cards. The other 20 come from a background call the page's own script makes when you scroll; the actor makes the same call on the same session, so you get all 50 per page and all 100 per list. Prices are parsed per locale ($1,234.56 and 20,46 € both work), the currency is set per marketplace, and the left-hand menu is read so you can pull every subcategory in one run. No browser; plain HTTP through residential proxies in the marketplace's country.

Python example

pip install apify-client
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")

run = client.actor("rel8ble/amazon-bestsellers-scraper").call(run_input={
    "categoryUrls": [
        "https://www.amazon.com/Best-Sellers-Electronics/zgbs/electronics/",
        "https://www.amazon.de/gp/new-releases/ce-de/",
    ],
    "maxItemsPerList": 100,
})

for p in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(p["marketplace"], p["rank"], p["asin"], p["price"], p["currency"], p["rating"], p["title"][:60])

Node example

npm install apify-client
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });

const run = await client.actor('rel8ble/amazon-bestsellers-scraper').call({
    categoryIds: ['electronics'],
    domain: 'amazon.co.uk',
    listType: 'bestsellers',
    maxItemsPerList: 50,
    includeSubcategories: true,
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
for (const p of items) console.log(p.listName, p.rank, p.asin, p.price, p.currency, p.title);

What a result looks like

{
    "rank": 1,
    "asin": "B08JHCVHTY",
    "title": "blink plus plan with monthly auto-renewal",
    "price": 11.99,
    "priceText": "$11.99",
    "currency": "USD",
    "rating": 4.4,
    "ratingsCount": 280900,
    "imageUrl": "https://images-na.ssl-images-amazon.com/images/I/31YHGbJsldL._AC_UL900_SR900,600_.png",
    "url": "https://www.amazon.com/dp/B08JHCVHTY",
    "listType": "bestsellers",
    "listName": "Best Sellers in Electronics",
    "categoryId": "electronics",
    "categoryPath": "Any Department > Electronics",
    "listUrl": "https://www.amazon.com/gp/bestsellers/electronics",
    "marketplace": "amazon.com",
    "page": 1,
    "scrapedAt": "2026-10-08T00:36:48.481Z"
}

A small project: a daily rank tracker

Schedule the actor once a day on the Apify platform (Schedules tab, pick the actor, paste the input), then append each day's dataset to a local SQLite table and chart any ASIN's rank over time:

import sqlite3, datetime as dt
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")
db = sqlite3.connect("ranks.db")
db.execute("""create table if not exists ranks(
    day text, marketplace text, list_url text, asin text, rank int, price real, rating real, ratings_count int, title text,
    primary key(day, list_url, asin))""")

# Latest finished run of the actor (the scheduled one)
runs = client.actor("rel8ble/amazon-bestsellers-scraper").runs().list(desc=True, limit=1).items
dataset_id = runs[0]["defaultDatasetId"]
day = dt.date.today().isoformat()

for p in client.dataset(dataset_id).iterate_items():
    db.execute("insert or replace into ranks values (?,?,?,?,?,?,?,?,?)",
               (day, p["marketplace"], p["listUrl"], p["asin"], p["rank"], p["price"], p["rating"], p["ratingsCount"], p["title"]))
db.commit()

# Which products climbed the most since yesterday?
for row in db.execute("""
    select t.asin, y.rank as yesterday, t.rank as today, t.title
    from ranks t join ranks y on y.asin = t.asin and y.list_url = t.list_url and y.day = date(t.day, '-1 day')
    where t.day = ? order by (y.rank - t.rank) desc limit 10""", (day,)):
    print(row)

One list a day is 100 results, or 15 cents, so a 20-category tracker runs for about $3 a month.

Things I learned building it

  • 30 vs 50: the "missing" 20 products per page aren't on page 2, they're lazy-loaded. If you scrape the HTML only, you get 60 of the 100 and a gap at ranks 31-50 and 81-100.
  • Prices: 97% of products on a 200-item test had one. The rest are subscriptions or out-of-stock items Amazon lists without a price.
  • Movers & Shakers, Most Wished For and Most Gifted currently render without a server-side product grid, so the actor only promises Best Sellers and New Releases. URLs of the other kinds are accepted and come back empty, with the reason in the run summary.
  • Residential proxies are the default. Datacenter IPs work for a while and then hit captchas; the actor retries on a fresh session, but residential is cheaper in retries than it costs in bandwidth (about 0.5 MB per page).

If something breaks or a field is wrong, the Issues tab on the actor page reaches me directly.

Amazon Best Sellers Scraper on Apify


This article was drafted with AI and published by me.

來源:DEV Community · dev.to