[ BLOG // 2026-08-02 // 3 MIN ]

Čtyři úrovně HTML, jeden JSON a Volvo: jak naparsovat katalog dílů bez API

Každá značka auta má v katalogu dílů jinou strukturu navigace. Volvo má čtyři úrovně, Nissan dvoufázový BOM. Ukážu, jak vypadá parser architektura, která tohle zvládá bez toho, aby se z toho stal nepořádek.

PROJEKTY AUTODILYWEB SCRAPINGPARSERNEXT.JSCASE STUDY

Katalogy autodílů nemají API. Mají HTML — a každá značka ho má jinak. Opel má dvě úrovně navigace a JSON subgroups. Volvo má čtyři úrovně a mixuje HTML s JSONem. Nissan má dvoufázový BOM, kde HTML stránka obsahuje jen kategorie dílů a teprve druhý request vrátí skutečná čísla.

Když potřebujete z takového katalogu tahat data programově, máte dvě možnosti: napsat jeden velký parser, který se větví podle značky, nebo navrhnout architekturu, kde každá značka řeší svoje specifika sama. První možnost funguje do třetí značky. Pak se z toho stane kód, který nikdo nechce číst.

Jedno rozhraní, každá značka vlastní parser

Základ je interface StrutsBrandParser. Definuje, co musí každá značka umět:

  • naparsovat subgroups z JSONu
  • naparsovat BOM (seznam dílů) z HTML
  • poznat, jestli je URL validní VIN stránka
  • vytáhnout session klíč z redirect parametru

Volitelně může značka přepsat parsování vehicle info, main groups a subgroups z HTML — to je klíčové pro značky, které nemají standardní layout.

Generic klient (struts-client.ts) řeší navigaci: follow redirectů, cookie auth, fetchování jednotlivých úrovní. Na parsování se ptá parseru konkrétní značky. Když Volvo vrátí HTML tam, kde Opel vrací JSON, klient to nemusí vědět — zavolá parseSubgroupsHtml a dostane normalizované VCfgEntry[], se kterými umí pracovat.

Volvo: čtyři úrovně, žádný JSON na začátku

Volvo je nejhlubší. Navigace vypadá takhle:

decode_vin
  → vin-group.action                    (level 1 — HTML, main groups)
  → vin-group.action?group1=X           (level 2 — HTML, subgroups)
  → json-vin-groups3.action             (level 3 — JSON, ilustrace)
  → vin-image-board.action              (level 4 — HTML, BOM)

Level 1 a 2 jsou HTML tabulky renderované přímo do stránky. Žádný JSON endpoint pro main groups neexistuje — parser musí číst #nav-group1-table a #nav-group2-table přímo z HTML.

Level 2 je zajímavý: každý řádek tabulky má atribut jsonurl, který ukazuje na level 3. Parser vrátí VCfgEntry[] s vyplněným jsonUrl a generic klient pak udělá follow-up fetch, který projde parseSubgroupsJson. Stejná logika jako u značek, které mají JSON od začátku — jen první krok je navíc.

Level 4 (BOM) má svoje mouchy. Řádky s valid="false" jsou díly, které se nedají objednat samostatně — parser je přeskočí. Název dílu může obsahovat <br> mezi základním názvem a suffixem left/right, takže cheerio .text() nestačí — je potřeba přepsat <br> na mezeru před extrakcí textu.

Session token je hintstoken= (UUID), ne catId= jako u Opelu. Malý detail, ale bez něj nefunguje auth.

Nissan: BOM ve dvou fázích

Nissan má jiný problém. BOM stránka (x-vin-image-board.action) neobsahuje skutečná čísla dílů — jen kategorie (PNC, part-number category). Teprve druhý request na x-json-vin-bom-detail.action?pnc=X vrátí reálné díly pro danou kategorii.

Proto má interface volitelný parseBomPartsAsync — asynchronní verzi BOM parseru. Nissan ho implementuje, ostatní značky ne. Klient zjistí, jestli parser async verzi má, a podle toho se rozhodne, kterou cestou jít.

Detail fetchů je omezený na 6 souběžných requestů — jednak aby to bylo slušné k serveru, jednak aby to nespadlo pod rate limit.

Testy proti zachyceným fixturám

Parser se netestuje proti živému katalogu. Byl by to flaky test — katalog se mění, session expirují, síť je nespolehlivá.

Místo toho se používají zachycené HTML a JSON fixtury z reálných requestů. Volvo parser má 17 unit testů proti fixturám z VIN YV1UZK5VCM1743449 (XC60, brzdy, level 2 → 51 Wheel brake → 416001). Testy pokrývají všechny čtyři úrovně: level 2 HTML, level 3 JSON, level 4 BOM.

Když se změní struktura katalogu, test spadne s jasnou chybou — ne s timeoutem nebo prázdným výsledkem.

Co z toho plyne

Parser architektura pro katalogy autodílů není o tom, napsat co nejchytřejší scraper. Je o tom, navrhnout rozhraní, které unese rozdíly mezi značkami, aniž by se generic klient musel starat o to, jestli zrovna čte HTML nebo JSON.

Volvo má čtyři úrovně. Nissan má dvoufázový BOM. Opel má JSON od začátku. Všechny tři vrací stejné typy — a klient, který je volá, o rozdílech neví.

Dobrá abstrakce není ta, která skrývá složitost. Je to ta, která ji izoluje na jedno místo.

// ALL_POSTS
ZPĚT NA BLOG