Product-market-fit research used to require hiring a freelancer to read hundreds of reviews. A review-mining agent does this in minutes. This tutorial builds one that pulls Amazon, Walmart, and Google reviews for a category, then clusters complaints into pain-point themes.
Prerequisites
- Python 3.10+
- A Scavio API key
- An LLM credential for clustering
- A product category
Walkthrough
Step 1: Pull Amazon reviews
Top sellers in the category.
import requests, os
API_KEY = os.environ['SCAVIO_API_KEY']
def amazon_reviews(category):
r = requests.post('https://api.scavio.dev/api/v1/search',
headers={'x-api-key': API_KEY},
json={'platform': 'amazon', 'query': category, 'marketplace': 'US'})
asins = [p['asin'] for p in r.json().get('products', [])[:10]]
revs = []
for a in asins:
rv = requests.post('https://api.scavio.dev/api/v1/search',
headers={'x-api-key': API_KEY},
json={'platform': 'amazon_reviews', 'query': a}).json()
revs += rv.get('reviews', [])
return revsStep 2: Pull Walmart reviews for cross-validation
Same category, different platform.
def walmart_reviews(category):
r = requests.post('https://api.scavio.dev/api/v1/search',
headers={'x-api-key': API_KEY},
json={'platform': 'walmart', 'query': category})
return r.json().get('products', [])[:10]Step 3: Filter to negative reviews
1-3 star reviews contain the pain.
def negatives(reviews):
return [r for r in reviews if r.get('rating', 5) <= 3]Step 4: Cluster pain points with an LLM
Group review texts into themes.
def cluster(reviews, llm):
prompt = 'Cluster these reviews into 5 pain-point themes:\n' + '\n'.join(r['text'] for r in reviews[:100])
return llm.generate(prompt)Step 5: Output report
Top 5 themes with representative quotes.
def report(themes):
for t in themes:
print(f'{t["name"]} ({t["count"]}): {t["quote"]}')Python Example
import os, requests
API_KEY = os.environ['SCAVIO_API_KEY']
def mine(category):
r = requests.post('https://api.scavio.dev/api/v1/search',
headers={'x-api-key': API_KEY},
json={'platform': 'amazon', 'query': category, 'marketplace': 'US'})
reviews = []
for p in r.json().get('products', [])[:5]:
rv = requests.post('https://api.scavio.dev/api/v1/search',
headers={'x-api-key': API_KEY},
json={'platform': 'amazon_reviews', 'query': p['asin']}).json()
reviews += [x for x in rv.get('reviews', []) if x.get('rating', 5) <= 3]
return reviews
print(len(mine('standing desk')))JavaScript Example
const API_KEY = process.env.SCAVIO_API_KEY;
export async function mine(category) {
const r = await fetch('https://api.scavio.dev/api/v1/search', {
method: 'POST',
headers: { 'x-api-key': API_KEY, 'Content-Type': 'application/json' },
body: JSON.stringify({ platform: 'amazon', query: category, marketplace: 'US' })
});
const products = (await r.json()).products?.slice(0, 5) || [];
const reviews = [];
for (const p of products) {
const rv = await fetch('https://api.scavio.dev/api/v1/search', {
method: 'POST',
headers: { 'x-api-key': API_KEY, 'Content-Type': 'application/json' },
body: JSON.stringify({ platform: 'amazon_reviews', query: p.asin })
});
reviews.push(...((await rv.json()).reviews || []).filter(x => x.rating <= 3));
}
return reviews;
}Expected Output
Top 5 pain-point themes for a category with representative quotes. Typical output for 'standing desk': wobble, assembly time, motor noise, price vs. feel, short cable.