BestPrice.gr API: τιμές, προσφορές και barcode σε JSON
Η λίστα αποτελεσμάτων μιας αναζήτησης ή κατηγορίας, τα καταστήματα που πουλούν ένα προϊόν με τις τιμές τους, η χαμηλότερη και η υψηλότερη τιμή του σε ευρώ: τα δημόσια στοιχεία του bestprice.gr έρχονται εδώ σε JSON, χωρίς εγγραφή στο BestPrice. Αν ο κατάλογός σας έχει barcode, η ενέργεια `barcode` βρίσκει απευθείας το αντίστοιχο προϊόν του BestPrice, εφόσον ο κωδικός υπάρχει στο ευρετήριό του, και γλιτώνετε την αντιστοίχιση με βάση τα ονόματα. Δεν απευθύνεται σε εμπόρους: δεν ανεβάζει XML feed και δεν συνδέεται με λογαριασμό εμπόρου στο BestPrice. Είναι η πλευρά του αγοραστή, όπως φαίνεται τη στιγμή της κλήσης.
Endpoints
| endpoint | Τι επιστρέφει | Υποχρεωτικά |
|---|---|---|
| search | Αναζήτηση με όρο στα ελληνικά ή στα αγγλικά: τίτλος, η τιμή που δείχνει το BestPrice (δηλαδή η χαμηλότερη) σε ευρώ, σε πόσα καταστήματα υπάρχει και το `product_id`. Όταν το site ανακατευθύνει την αναζήτηση σε σελίδα κατηγορίας ή μάρκας, το `redirected_to` δείχνει ποια. Κάποιες γραμμές είναι αγγελία ενός μόνο καταστήματος (`listing_type: shop_offer`) και δεν έχουν `product_id`. | query |
| category | Η λίστα μιας κατηγορίας χωρίς λέξη-κλειδί, με το αριθμητικό id της (π.χ. `806` για τα κινητά) ή το URL της· το προαιρετικό `query` περιορίζει τα αποτελέσματα. Οι γραμμές έχουν την ίδια μορφή με το search. | category_id |
| product | Ένα προϊόν με τις προσφορές των καταστημάτων (κατάστημα, τιμή, διαθεσιμότητα), το εύρος τιμών στην αγορά (`price_low_eur`, `price_high_eur`, `offer_count`), τη διαδρομή κατηγορίας και το barcode του (`gtin` μαζί με `gtin_type`). | product_id |
| barcode | Βρίσκει το `product_id` του BestPrice από EAN-13, EAN-8, UPC-12 ή GTIN-14. Κάθε γραμμή έχει `match_type`· από προεπιλογή επιστρέφονται μόνο όσες το ίδιο το BestPrice δηλώνει ως ακριβή αντιστοίχιση (`barcode_exact`). | barcode |
Κάθε κλήση χρεώνεται σε credits. Οι αποτυχημένες και μπλοκαρισμένες κλήσεις είναι δωρεάν.
Παράδειγμα που δουλεύει
Το BestPrice δεν έκανε αναζήτηση κειμένου: ανακατεύθυνε το ερώτημα στην κατηγορία «Κλιματιστικά με Inverter» (2442), οπότε οι 16 γραμμές είναι η λίστα αυτής της κατηγορίας, όπως δηλώνει το `redirected_to`. Σε κάθε γραμμή το `price_eur` αντιστοιχεί στο φθηνότερο κατάστημα· τις τιμές των υπόλοιπων τις φέρνει το `product` με το ίδιο `product_id`. Για το Toyotomi Umi παρακάτω, το `product` μέτρησε 47 καταστήματα, με τιμές από 417 έως 669 €.
curl -X POST https://api.reefapi.com/bestprice/v1/search \
-H "x-api-key: ΤΟ_ΚΛΕΙΔΙ_ΣΑΣ" \
-H "content-type: application/json" \
-d '{"query": "κλιματιστικό inverter"}'{
"ok": true,
"data": {
"products": [
{
"listing_type": "product",
"product_id": "2159736789",
"title": "Morris Terra WFIN-35180 Κλιματιστικό Inverter 12000 BTU A+++/A+++ με Ιονιστή και Wi-Fi",
"price_eur": 223.87,
"currency": "EUR",
"category_id": "2442",
"shop_count": 14
},
...
{
"listing_type": "product",
"product_id": "2159740957",
"title": "Toyotomi Umi UTN-12CH/UTG-12CH Κλιματιστικό Inverter 12000 BTU A+++/A+++ με Ιονιστή και Wi-Fi",
"price_eur": 417.0,
"currency": "EUR",
"category_id": "2442",
"shop_count": 47
},
...
],
"page": 1,
"limit": 24,
"query": "κλιματιστικό inverter",
"redirected_to": {
"type": "category",
"id": "2442",
"title": "Κλιματιστικά με Inverter",
"url": "https://www.bestprice.gr/cat/2442/air-condition/f/71_1/inverter.html"
}
},
"meta": { "record_count": 16, "cache_hit": false, "mode": "live" }
}Τι θα συναντήσει ένας δικός σας scraper στο BestPrice
Το πρώτο εμπόδιο εμφανίζεται πριν καν φτάσετε στο HTML. Το bestprice.gr κόβει τη σύνδεση ανάλογα με το TLS αποτύπωμα του client: με τα προφίλ Chrome και Firefox που μιμούνται οι βιβλιοθήκες HTTP, η σύνδεση πέφτει από όποιο δίκτυο κι αν δοκιμάσαμε, χωρίς καν σελίδα σφάλματος. Μοιάζει με πεσμένο site ή με μπλοκαρισμένη IP, όμως η αλλαγή IP δεν το λύνει· το κρίσιμο είναι το αποτύπωμα.
Οι τιμές στις κάρτες της λίστας (`data-price` στο HTML) είναι σε λεπτά του ευρώ: 61000 σημαίνει 610,00 €. Αν τις διαβάσετε ως ευρώ, βγαίνουν εκατό φορές μεγαλύτερες. Εδώ έρχονται ήδη σε ευρώ στο `price_eur`· τις συγκρίναμε με την τιμή που εμφανίζεται στην κάρτα και συμφώνησαν 48 στις 48.
Στις μετρήσεις μας το `pg=2` ανακατεύθυνε πίσω στη σελίδα 1, παρότι η σελίδα δηλώνει ότι υπάρχει επόμενη (`rel="next"`). Ένα script που ζητά `pg=2`, `pg=3` μαζεύει ξανά και ξανά τα ίδια 16 προϊόντα. Εδώ κάθε σελίδα μετά την πρώτη επιστρέφει 0 γραμμές και `page_available: false`, ώστε να μη μετρηθούν διπλά.
Τέλος, η αναζήτηση του site δεν βρίσκει barcode: 12 EAN που δημοσιεύει το ίδιο το BestPrice στις σελίδες των προϊόντων του έφεραν 12 φορές «Δεν βρέθηκαν». Γι' αυτό το `barcode` είναι ξεχωριστή ενέργεια.
Περισσότερη τεκμηρίωση στα ελληνικά
Όρια και ειλικρινείς σημειώσεις
- Η υπηρεσία δεν προέρχεται από το BestPrice.gr: δεν είναι επίσημο API του, ούτε συνεργαζόμαστε μαζί του.
- Επιστρέφεται μόνο η πρώτη σελίδα κάθε λίστας, δηλαδή έως 16 προϊόντα· το `page` πάνω από 1 δεν φέρνει νέα. Για περισσότερα προϊόντα, κάντε την αναζήτηση πιο συγκεκριμένη ή ζητήστε μια πιο στενή κατηγορία.
- Το `product` φέρνει όσες προσφορές φορτώνει αρχικά η σελίδα του προϊόντος (30 σε κάθε προϊόν που μετρήσαμε, βλ. `offers_listed`), ενώ το `offer_count` μετράει όλη την αγορά: για το ψυγείο LG GBB566PZHMN, 48 καταστήματα και 30 στη λίστα. Το `price_high_eur` (εκεί 1.218,99 €) μπορεί να μην αντιστοιχεί σε καμία γραμμή του `offers[]`· στο ίδιο ψυγείο η ακριβότερη προσφορά της λίστας ήταν 849 €.
- Το `url` κάθε προσφοράς έρχεται null: σύνδεσμος προς τη σελίδα του καταστήματος δεν επιστρέφεται (60 στις 60 προσφορές σε δύο προϊόντα που ελέγξαμε).
- Το `barcode` δεν καλύπτει κάθε κωδικό: από 36 barcode που πήραμε από σελίδες του BestPrice βρέθηκαν τα 25. Στα ηλεκτρονικά και στις οικιακές συσκευές βρέθηκαν 3 στα 3, στο σούπερ μάρκετ και στα καλλυντικά 1 στα 3, στην κατηγορία PlayStation 0 στα 3. Κενή απάντηση σημαίνει ότι ο κωδικός δεν υπάρχει στο ευρετήριο barcode του BestPrice, όχι σφάλμα. Τότε μένει η διαδρομή `search` → `product`· το `product` επιστρέφει το `gtin`, που υπήρχε σε 36 από τις 36 σελίδες προϊόντων που ελέγξαμε.
- Η διαθεσιμότητα δεν έχει παντού το ίδιο λεξιλόγιο: στο `product` είναι `InStock` / `BackOrder`, στο `barcode` είναι `available`.