Mitä rakennat
Palvelinpuolen komentoriviohjelma hakee enintään kolme sivua tuotteita, antaa sinun valita kaksi tuotetunnistetta ja tulostaa niiden havaitut toimitetut hinnat. Valitse TypeScript tai Python: työnkulku on sama. Ohjelma vain lukee tietoa eikä luo vahteja tai ostoja.
Valmistele avain ja ajoympäristö
Tarvitset Node.js 22.13+:n ja npm:n tai Python 3.11+:n ja uv:n. Asenna alla oleva SDK tyhjään projektihakemistoon. Luo testiympäristön avain catalog:read- ja compare:read-oikeuksilla sekä vastaavilla tilauksen käyttöoikeuksilla. Aseta HINTADATA_API_KEY yksityisesti prosessin ympäristöön; älä lisää sitä lähdekoodiin, selainkoodiin tai versionhallintaan. Aloita esimerkkidataa palauttavalla testiavaimella. Tuotantoavain tarvitsee tuoreen lähdeaineiston ja voi kuluttaa käyttökiintiötä.
TypeScript
npm init -y
npm install https://hintadata.fi/sdk/price-compare-typescript-3.1.0.tgz
npm install --save-dev typescript tsx @types/nodeTallenna koko ohjelma nimellä compare.ts.
import { Configuration, CatalogApi, ComparisonsApi, ResponseError } from '@pricecompare/sdk';
async function main() {
const key = process.env.HINTADATA_API_KEY;
if (!key) throw new Error('Set HINTADATA_API_KEY privately.');
const config = new Configuration({
basePath: 'https://hintadata.fi/v1', accessToken: key,
fetchApi: (url, init) => fetch(url, { ...init, signal: AbortSignal.timeout(20000) }),
});
const catalog = new CatalogApi(config);
const comparisons = new ComparisonsApi(config);
const query = process.argv[2] || 'sony';
const selected = process.argv.slice(3);
const candidates = new Map<string, string>();
let offset = 0;
// Bound time and usage; follow the server cursor, not a guessed page number.
for (let page = 0; page < 3; page++) {
const result = await catalog.searchProducts({ q: query, limit: 2, offset });
for (const item of result.items) candidates.set(item.canonical_product_id, item.product_name);
if (result.next_offset == null) break;
if (!Number.isInteger(result.next_offset) || result.next_offset <= offset) throw new Error('Invalid pagination cursor.');
offset = result.next_offset;
}
if (!candidates.size) { console.log('No matches. Refine your query.'); return; }
if (!selected.length) {
console.table([...candidates].map(([id, name]) => ({ id, name })));
console.log('Run again with two distinct IDs from the same comparable category. At most three pages are read.');
return;
}
if (selected.length !== 2 || new Set(selected).size !== 2 || selected.some(id => !candidates.has(id))) {
throw new Error('Select two distinct IDs from these search results. Refine the query if necessary.');
}
const result = await comparisons.compareProducts({ ids: selected.join(',') });
for (const product of result.products) {
const offer = product.best_offer;
console.log(JSON.stringify({ id: product.canonical_product_id, name: product.comparison_name,
delivered_price: offer?.delivered_price ?? null }));
}
console.log('Observed offers, not a purchase guarantee. Review availability, observation time and seller terms before deciding.');
}
main().catch(error => {
console.error(error instanceof ResponseError ? 'API request failed: HTTP ' + error.response.status + '. See Errors and limits.' : 'Integration stopped. Check configuration, query and selected IDs.');
process.exitCode = 1; // Never print credentials, raw response bodies or an SDK exception.
});npx tsx compare.ts sony
# Replace these with two IDs printed by the first command.
npx tsx compare.ts sony CANONICAL_ID_1 CANONICAL_ID_2Python
uv venv
uv pip install https://hintadata.fi/sdk/price_compare-3.1.0.tar.gzTallenna koko ohjelma nimellä compare.py.
import asyncio
import os
import sys
import price_compare
from price_compare.api.catalog_api import CatalogApi
from price_compare.api.comparisons_api import ComparisonsApi
from price_compare.exceptions import ApiException
async def main():
key = os.environ.get("HINTADATA_API_KEY")
if not key:
raise ValueError("Set HINTADATA_API_KEY privately")
config = price_compare.Configuration(host="https://hintadata.fi/v1")
config.access_token = key
query = sys.argv[1] if len(sys.argv) > 1 else "sony"
selected = sys.argv[2:]
candidates = {}
offset = 0
async with price_compare.ApiClient(config) as client:
catalog = CatalogApi(client)
comparisons = ComparisonsApi(client)
for _ in range(3):
result = await catalog.search_products(q=query, limit=2, offset=offset, _request_timeout=20.0)
for item in result.items:
candidates[item.canonical_product_id] = item.product_name
if result.next_offset is None:
break
if result.next_offset <= offset:
raise ValueError("Invalid pagination cursor")
offset = result.next_offset
if not candidates:
print("No matches. Refine your query.")
return
if not selected:
for identity, name in candidates.items():
print(identity, name)
print("Run again with two distinct IDs from the same comparable category. At most three pages are read.")
return
if len(selected) != 2 or len(set(selected)) != 2 or any(identity not in candidates for identity in selected):
raise ValueError("Select two distinct IDs from these search results")
result = await comparisons.compare_products(ids=",".join(selected), _request_timeout=20.0)
for product in result.products:
offer = product.best_offer
print(product.canonical_product_id, product.comparison_name,
offer.delivered_price if offer else None)
print("Observed offers, not a purchase guarantee. Review availability, observation time and seller terms before deciding.")
if __name__ == "__main__":
try:
asyncio.run(main())
except ApiException as error:
print("API request failed: HTTP", error.status, "See Errors and limits.", file=sys.stderr)
sys.exit(1)
except Exception:
print("Integration stopped. Check configuration, query and selected IDs.", file=sys.stderr)
sys.exit(1)
uv run --no-project python compare.py sony
# Replace these with two IDs printed by the first command.
uv run --no-project python compare.py sony CANONICAL_ID_1 CANONICAL_ID_2Valitse tuotteet tarkoituksella
Ensimmäinen ajo tulostaa kanoniset tunnisteet ja nimet, ei suositusta. Valitse kaksi eri tuotetta samasta vertailukelpoisesta kategoriasta ja tarkista malli sekä variantti API-viitteestä. Toinen ajo tarkistaa valintasi rajatusta hausta ennen compareProducts-kutsua. Ohjelma ei valitse kahta ensimmäistä osumaa puolestasi. Jos haluttu tunniste jää kolmen ensimmäisen sivun ulkopuolelle, tarkenna hakua. next_offset on palvelimen jatkoarvo; null tarkoittaa listan loppua.
Tunnista onnistunut tulos
Toinen ajo tulostaa rivin kustakin vertailtavasta tuotteesta: kanonisen tunnisteen, vertailunimen ja best_offer.delivered_price-arvon. Puuttuva arvo säilyy puuttuvana, ei nollana. Kyse on havaituista tarjouksista, ei ennusteesta, varauksesta tai ostotakuusta. Tarkista ennen hinnan käyttöä tarjouksen saatavuus, havaintoaika ja myyjän ehdot täydestä tyypitetystä vastauksesta. Älä päättele valuuttaa tai verokäsittelyä nimettömästä luvusta.
Käsittele tyhjät tulokset ja virheet
Tyhjä haku on normaali tulos: tarkenna hakua. Toistuvat, tuntemattomat tai liian monet valitut tunnisteet pysäyttävät ohjelman ennen vertailua. Pyyntöjen aikaraja on 20 sekuntia eikä automaattista uudelleenyritystä tehdä. HTTP-virhe päättää ajon virhetilaan ja tulostaa vain tilakoodin, ei raakaa SDK-poikkeusta. Tarkista 401-virheessä avain, 403-virheessä oikeudet ja tilaus. 503 source_unavailable/source_stale edellyttää lähteen omistajan toimia. Älä korvaa puuttuvaa tuotantoaineistoa demodatalla. Noudata tilapäisissä 429/5xx-virheissä rajattua retry-ohjetta ennen uutta ajoa; älä rakenna rajatonta silmukkaa.