Siirry dokumentaation sisältöön
HintadataDocs

Rakenna haku- ja vertailuintegraatio

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.

Tässä oppaassa
  1. 1Mitä rakennat
  2. 2Valmistele avain ja ajoympäristö
  3. 3TypeScript
  4. 4Python
  5. 5Valitse tuotteet tarkoituksella
  6. 6Tunnista onnistunut tulos
  7. 7Käsittele tyhjät tulokset ja virheet
Tässä oppaassa
  1. 1Mitä rakennat
  2. 2Valmistele avain ja ajoympäristö
  3. 3TypeScript
  4. 4Python
  5. 5Valitse tuotteet tarkoituksella
  6. 6Tunnista onnistunut tulos
  7. 7Käsittele tyhjät tulokset ja virheet

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

bashillustrative
Esimerkin luotettavuus: illustrativeNäyttää muodon tai idean; älä käytä sellaisenaan tuotannossa.
npm init -y
npm install https://hintadata.fi/sdk/price-compare-typescript-3.1.0.tgz
npm install --save-dev typescript tsx @types/node

Tallenna koko ohjelma nimellä compare.ts.

typescriptillustrative
Esimerkin luotettavuus: illustrativeNäyttää muodon tai idean; älä käytä sellaisenaan tuotannossa.
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.
});
bashillustrative
Esimerkin luotettavuus: illustrativeNäyttää muodon tai idean; älä käytä sellaisenaan tuotannossa.
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_2

Python

bashillustrative
Esimerkin luotettavuus: illustrativeNäyttää muodon tai idean; älä käytä sellaisenaan tuotannossa.
uv venv
uv pip install https://hintadata.fi/sdk/price_compare-3.1.0.tar.gz

Tallenna koko ohjelma nimellä compare.py.

pythonillustrative
Esimerkin luotettavuus: illustrativeNäyttää muodon tai idean; älä käytä sellaisenaan tuotannossa.
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)
bashillustrative
Esimerkin luotettavuus: illustrativeNäyttää muodon tai idean; älä käytä sellaisenaan tuotannossa.
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_2

Valitse 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.

Oliko tästä sivusta apua?