Cheerio potřeboval na stránce o velikosti 10 MB v Node 2,9 sekundy

Naposledy aktualizováno August 19, 2026
Cheerio potřeboval na stránce o velikosti 10 MB v Node 2,9 sekundy
AI shrnutí
Na jednom stroji dokázal cheerio v Node zpracovat a vytáhnout názvy i hrefy z umělého HTML dokumentu o velikosti 10 MB za 2 927,89 ms. selectolax spuštěný přes CPython s parserem s podporou C dokončil stejnou extrakci polí za 158 ms. Seřazené texty nadpisů a hashy hrefů se shodovaly. Jde o porovnání celého stacku napříč runtime prostředími, ne o izolovaný verdikt nad parserovým algoritmem. Na stránce o 10 KB je rozdíl 2× a nikdo by si ho nevšiml. Hlavní otázka je, kde se vaše stránky na téhle křivce nacházejí. Použijte cheerio, pokud jste v Node, hodí se vám API ve stylu jQuery a vaše reprezentativní stránky se podobají testovaným velikostem až do 1 MB.

Na jednom stroji cheerio v Node parsoval a z 10MB syntetického HTML dokumentu vytáhl názvy i hrefy za 2 927,89 ms. selectolax, běžící přes CPython s parserem v C, zvládl stejnou extrakci polí za 158 ms. Seřazený text názvů i hashy hrefů se shodovaly. Jde o porovnání celého stacku napříč runtime prostředími, ne o verdikt nad izolovaným algoritmem parseru.

Na 10KB stránce je rozdíl dvojnásobný a nikdo si ho nevšimne. Celá otázka zní: kde vaše stránky na té křivce leží.

Co je cheerio

cheerio je HTML parser pro Node se syntaxí připomínající jQuery a v tomto ekosystému je z dobrého důvodu výchozí odpovědí: 30 449 hvězdiček na GitHubu, licence MIT a commit do repozitáře den před mým testem. Otestovaná verze: 1.2.0.

Oficiální reference: oficiální úvod do Cheeria.

import * as cheerio from "cheerio";
const $ = cheerio.load(html);
const titles = $("h3.title").map((_, e) => $(e).text()).get();
const hrefs = $("a").map((_, e) => $(e).attr("href")).get();

Pokud jste někdy psali jQuery, API už znáte. Právě tahle známost je velká část důvodu, proč v tomhle ekosystému vyhrálo.

Pod kapotou to není jeden parser, ale celý stack: htmlparser2 a parse5 pro parsování, domhandler a domutils pro strom, cheerio-select pro selektory, plus undici, encoding-sniffer a další — jedenáct přímých závislostí, které se po rozbalení promítají do 22 balíčků na nejvyšší úrovni a 9,0 MiB na disku. Tyto balíčky zajišťují parsování i práci s kódováním a zároveň přidávají váhu do závislostního stromu. Tato recenze testovala chování na poškozeném vstupu, ale netestovala správnost kódování ani neoddělovala oba parserové backendy.

Měření a proč mu lze věřit

Základ tohoto výzkumu už měl parser benchmark: pět velikostí stránek od 1 KB do 10 MB, 50 iterací, tři nezávislé běhy a — to podstatné — paritní kontrolu, která hashovala extrahovaný obsah: seřazené názvy plus seřazené hrefy proti referenčnímu parseru. Parser, který tiše vynechá část práce, nemůže vyprodukovat rychlý čas.

Přidání cheeria si před započítáním jakýchkoli čísel vyžádalo dvě kontroly.

Sedí reference tam, kde seděla předtím? selectolax byl znovu spuštěn ve stejné relaci a na stejných testovacích datech. Jeho content hash se zopakoval na 5 z 5 velikostí a p50 vyšel mezi 0,989× a 1,079× publikované hodnoty. Takže jde o stejný stroj, který vytvořil původní tabulku.

Vyprodukovalo cheerio stejné vyhodnocené pole? Jeho content hash — spočítaný v Node se stejným pravidlem, tedy SHA-256 nad seřazeným textem názvů a seřazenými hrefy — se shodoval s referencí na 5 z 5 velikostí. To prokazuje paritu těchto seřazených polí na daných testovacích datech, ne shodu DOM stromu, pořadí dokumentu, atributů, normalizace textu ani obnovy po chybách.

Teprve potom mají timingy smysl.

Velikost stránkyselectolaxlxmlPyQuerycheerio (Node)cheerio vs selectolax
1 KB0.0286 ms0.05080.04560.1147 ms4.0×
10 KB0.1725 ms0.18020.17280.3490 ms2.0×
100 KB1.4855 ms1.41451.40933.8399 ms2.6×
1 MB14.97 ms15.0314.9659.37 ms4.0×
10 MB158.10 ms165.25162.862 927.89 ms18.5×

p50 v milisekundách, medián ze tří běhů. parser-bench.json. Tři Python parsery běžely v jednom procesu; cheerio běželo v Node 22, což je hranice nejen knihovny, ale i runtime prostředí — viz níže.

Jak tu tabulku číst poctivě

Measured results chart: Parser time across page sizes

Řádek 1 KB je šum. Mezi třemi Python parsery byl v téhle velikosti rozptyl 77,6 % a jednotlivé běhy se divoce překrývaly — selectolax se v rámci tří běhů pohyboval od 0,0267 do 0,0404 ms. Při 28 mikrosekundách dominují přesnost časovače i plánování procesů. Na 1 KB bych nic nehodnotil, ani cheerio.

Střed tabulky není ničím výjimečný. 2× až 4× na stránkách mezi 10 KB a 1 MB. U scraperu, který zpracuje pár stovek stránek, to znamená 45 ms na stránku místo 15 a v praxi si toho nevšimnete.

Řádek 10 MB už není šum. Tři běhy cheeria vyšly na 2 839, 2 928 a 2 954 ms — těsně u sebe a jasně oddělené od ostatních řádků. End-to-end výsledek pro 10 MB se prudce odchyluje od vzoru menších velikostí. Pět bodů v ose velikosti ale nestačí k určení asymptotické složitosti ani k tomu, abychom řekli, která vrstva — runtime, parser, selektory, alokace nebo garbage collection — ten skok způsobuje.

Spadá do pásma BeautifulSoup. Publikovaný benchmark měřil na stejném 10MB vzorku ještě čtyři další parsery a vedle nich je číslo cheeria 2 927,89 ms nejpoužitelnější údaj v celém článku:

Parser (10 MB)p50
selectolax (lexbor)159.93 ms
lxml172.93 ms
parsel231.85 ms
selectolax (modest)247.95 ms
BeautifulSoup + lxml2 261.56 ms
BeautifulSoup + html.parser2 788.75 ms
cheerio2 927.89 ms

Čtyři Python řádky jsou publikované hodnoty z bench_parse.json; cheerio je z tohoto běhu. Referenční parser se mezi oběma měřeními zopakoval v rozmezí 0,989×–1,079×, takže rozdíly menší než zhruba 8 % berte jako hranici této nejistoty — cheerio proti backendu html.parser u BeautifulSoup (rozdíl 5 %) do ní spadá, cheerio proti selectolaxu (18×) ne.

BeautifulSoup je knihovna, po které lidé sáhnou, když chtějí pohodlí a smíří se s tím, že je pomalá — je to ta, kterou v každé Python debatě o výkonu doporučují nahradit. Na 10MB dokumentu cheerio leží na spodku stejného pásma, ne v pásmu C-backed parserů, se kterými bývá často řazeno.

Otázka náhrady na straně Node v tomto článku zůstává otevřená. Novější alternativy pro Node nebyly testovány, takže z tohoto výsledku nelze vyvozovat, že výměna knihovny není možná nebo že by byly méně zavedené. Ukazuje to pouze změřenou cestu cheeria proti uvedeným Python stackům.

Je to porovnání runtime prostředí i knihovny. Milisekundy cheeria pocházejí z JITu a garbage collectoru v Node; ostatní čísla z CPythonu volajícího do parserů v C. Content hash potvrzuje, že se provedla stejná práce, a obě čísla jsou přesně to, co vývojář při volbě stacku skutečně zažívá — ale nikdo by z toho neměl číst, že „algoritmus cheeria je 18× horší než algoritmus selectolaxu“. Tak to prostě dopadlo na tomhle stroji v nativním runtime každé z knihoven.

Reálné nastavení

KnihovnaBalíčkyDiskLicenceHvězdyPoslední push
cheerio22 (npm)9.0 MiBMIT30 4492026-08-11
PyQuery3 (pip)20.1 MiBBSD2 3802026-07-27

Oficiální reference: dokumentace konfigurace Cheeria.

metadata-snapshot.json, stažené v den psaní.

npm install cheerio trvalo méně než dvě sekundy a stáhlo 9,0 MiB. Studený import naměřil ve zvláštním konverzním běhu na stejném stroji 0,056 s.

Jedenáct přímých závislostí je na parser dost hodně a stojí za to to vědět, pokud auditujete strom závislostí: htmlparser2, parse5, parse5-htmlparser2-tree-adapter, parse5-parser-stream, domhandler, domutils, dom-serializer, cheerio-select, encoding-sniffer, undici a whatwg-mimetype. Jsou v tom dodané dvě plnohodnotné parserové implementace, protože cheerio může používat kteroukoliv z nich podle toho, co po něm chcete.

Třicet tisíc hvězdiček a commit den před testem jsou v této kategorii asi nejzdravější signály údržby, které můžete chtít.

Paměť a co s ní udělá rozbitý HTML

Paměťová stopa a chování na poškozeném vstupu ovlivňují nasazení i ošetření chyb, proto jsou zde měřeny odděleně.

Širší kontext zátěžového testu je v porovnání paměti a rozbitého HTML pro deset knihoven.

Špičková rezidentní paměť, měřená přes /usr/bin/time -l, vždy jeden čerstvý proces na buňku — importní minimum je cena knihovny po načtení a v klidu, špičky zahrnují dokument.

KnihovnaRuntimeImport minimumŠpička 226 KBŠpička 10 MB
html2textpython3.1418.719.971.2
pyquerypython3.1430.333.9172.5
resiliparsepython3.1420.525.1225.1
markdownifypython3.1423.928.9278.5
goose3python3.1444.152.4398.5
cheerionode2266.876.5398.5
justextpython3.1430.336.6431.2
newspaper4kpython3.1452.661.8668.5
trafilaturapython3.1452.564.8927.1
turndownnode2247.868.42947.1

memory-results.json. Python a Node baseline nejsou navzájem přímo srovnatelné; interpret je uvnitř obou.

cheerio má v této smíšené tabulce nejvyšší importní minimum 66,8 MiB, včetně Node runtime a závislostí. Proces se na 10MB vzorku vyšplhal na 398,5 MiB. Ostatní řádky zahrnují parsery, převodníky a extraktory článků, které dělají jinou hlavní práci, takže je berte jako kontext k procesní stopě, ne jako férové pořadí výkonu. Řádek turndown ve stejném runtime sice vystřelil výrazně výš, ale dělá konverzi, ne kontrakt extrakce názvů a hrefů měřený u cheeria.

Rozbité HTML. Dvanáct dokumentů, z nichž každý porušuje přesně jednu věc — neuzavřené tagy, špatně vnořené inline elementy, neuvedené uvozovky u atributů s mezerami, osamocené uzavírací tagy, žádné <html>, duplicitní atributy, dokument uříznutý uprostřed tagu, špatné entity, neuzavřený <script>, lživé tvrzení o kódování, komentář obsahující značky a 600 úrovní zanoření — a k tomu dva dobře vytvořené kontrolní vzorky ve stejných velikostech, protože „nic nevrátil“ něco vypovídá o poškozenosti jen tehdy, když knihovna mlčí i nad čistým dokumentem stejné velikosti.

cheerio vyhodilo chybu na 0 z 14 a nevrátilo nic na 0, přičemž na poškozených testech obnovilo 11/22 hodnocených sentinelů (malformed-results.json). U parserů scorer kontroluje sentinelové nadpisy a odkazy napříč jedenácti hodnotitelnými poškozenými dokumenty; nehodnotí paragrafový sentinel a test s neuzavřeným <script> vylučuje. Bez baseline se stejným kontraktem v této části není 11/22 žádné pořadí kvality. Podporovatelný závěr je, že cheerio na všech čtrnácti poškozených i kontrolních vstupech vrátilo neprázdný výstup bez vyhození výjimky a zároveň obnovilo polovinu hodnocených markerů.

Klady a zápory

Ve prospěch. Známá syntaxe jQuery. MIT. Zdravý signál údržby v podobě 30 449 hvězdiček a aktivity v repozitáři den před testem. K dispozici jsou dva parserové backendy i balíčky související s kódováním, i když zotavení backendu a přesnost kódování zde nebyly izolovaně testovány. Hash seřazených názvů a hrefů se na každé velikosti fixture shodoval s referencí.

Proti. Na 10MB dokumentu je 18,5× pomalejší než selectolax a na 1 MB 4×. Jedenáct přímých závislostí, včetně dvou kompletních parserových implementací. Jen pro Node. A v dokumentaci nic nenasvědčuje velikosti, od níž by přestalo být očividnou volbou.

Kdo by ho měl použít a kdo ne

Použijte cheerio, pokud jste v Node, oceňujete API ve stylu jQuery a vaše typické stránky se drží rozměrů testovaných až do 1 MB. Jeden megabajt je největší testovaný bod před prudkým skokem na 10 MB; tento článek neurčuje hranici mezi nimi ani netvrdí, jak velká část webu leží pod ní.

Před použitím otestujte benchmarkem, pokud zpracováváte velmi velké HTML dokumenty, jako jsou generované reporty, exporty katalogů nebo dlouhé seznamové stránky. Chování XML sitemap nebylo testováno. Na 10MB HTML vzorku je 2,9 sekundy na dokument citelný náklad, který se nasčítá.

Pokud jste v Pythonu, říká toto srovnání něco jiného: selectolax, lxml a PyQuery jsou od 10 KB výše prakticky na stejné úrovni (v rozmezí 0,5 % až 5,4 % a s překrývajícími se rozsahy běhů), takže rozhodujte podle API, ne podle rychlosti. Zajímavé číslo je rozdíl cheeria vůči všem třem, ne rozdíly mezi nimi.

Kde dává smysl spravované API

cheerio parsuje HTML, které už máte. Nestahuje obsah, nespouští JavaScript ani neřeší anti-bot vrstvu — a u mnoha reálných cílů je právě tahle polovina práce ta těžší.

Spravovaná služba pro fetch/render/extrakci, včetně naší Thunderbit, stojí na jiné hranici odpovědnosti. Thunderbit zde nebyl benchmarkován. Důležitý rozdíl je mezi parsováním dodaného HTML pomocí selektorů a outsourcingem získání, renderování a extrakce; tento článek nenabízí srovnání kvality, latence ani ceny na stejné metricky.

Správné uchopení je jednoduché: pokud HTML držíte v ruce a znáte své selektory, cheerio je zdarma a příjemné na používání. Pokud stránky stahujete ve velkém nebo raději popisujete data než DOM, je to jiný nákup.

Pro širší přehled pokrývá náš souhrn Web Scraping API hostované možnosti a přehled open-source scraperů ty self-hosted. Pokud má být parsed output vstupem pro model, převod HTML do Markdownu v Pythonu ukazuje, kde se ztrácí věrnost.

Vyzkoušejte Thunderbit pro extrakci webových dat

Měli byste používat cheerio?

Ano, v Node, když je důležitá shoda API a reprezentativní dokumenty zůstávají poblíž testovaného rozsahu od malých velikostí do 1 MB.

Známost API a aktuální signály údržby jsou legitimní vstupy pro výběr. Benchmark nedokazuje, že existuje konkrétní podpůrná odpověď, ani že testované rozložení velikostí stránek odpovídá produkčnímu korpusu.

Číslo, které si máte zapamatovat, je to pro 10 MB. Někde mezi 1 MB a 10 MB přestane cena cheeria držet krok s ostatními a začne se násobit — 4× se změní na 18,5×. Pokud váš korpus obsahuje takto velké dokumenty, zbenchmarkujte to dřív, než se zavážete, protože vám na to samotná knihovna žádné varování nedá.

Vyzkoušejte Thunderbit pro extrakci webových dat Get Started Free

Časté dotazy

Je férové porovnávat cheerio s Python parsery? Je to porovnání stacků, ne algoritmů. Všechny čtyři varianty vrátily podle hash pravidla na 5 z 5 velikostí stejné seřazené texty názvů i hrefy. To ale neprokazuje úplnou ekvivalenci parserů. Timings cheeria zahrnují chování Node runtime, zatímco ostatní zahrnují CPython volající parsery v C; srovnání popisuje tato end-to-end rozhodnutí.

Proč se řádek 1 KB nehodnotí? Protože při 28 mikrosekundách měření převládá šum. Napříč třemi běhy měly Python parsery rozptyl 77,6 % a jednotlivé běhy se navzájem překrývaly. Jakékoli pořadí v téhle velikosti by bylo artefaktem. Od 10 KB výš je čtení stabilní.

Co způsobuje skok na 10 MB? Tento test to neříká. Co ale prokazuje, je, že skok je skutečný a ne šum: tři běhy cheeria skončily na 2 839, 2 928 a 2 954 ms, jasně oddělené od všeho ostatního, zatímco rozdíl u 1 MB byl 4×. Izolování příčiny by vyžadovalo samostatný profiling parserových backendů cheeria, což bylo mimo rozsah.

Kolik má opravdu závislostí? Jedenáct přímých, po rozbalení 22 na nejvyšší úrovni, 9,0 MiB na disku. Dvě z nich jsou kompletní parserové implementace — htmlparser2 a parse5 — protože cheerio může použít kteroukoliv z nich. To je cena za podporu jak tolerantního, tak specifikaci odpovídajícího parsování, a stojí za to ji znát při auditu stromu závislostí.

Co se zde netestovalo? Testy pokrývaly špičkovou paměť procesu na jednom dokumentu o 226 KB a jednom o 10 MB, plus sadu 14 poškozených i kontrolních vstupů, kde cheerio nevyhodilo chybu na žádném, na všech vrátilo neprázdný výstup a obnovilo 11/22 hodnocených sentinelů. Nepokrývaly streaming přes parse5-parser-stream, správnost kódování, zotavení specifické pro backend, umístění výkonového skoku mezi 1 a 10 MB, parsování XML ani novější alternativy pro Node.

Ke
Ke
CTO ve Thunderbit | Senior Data Scientist a expert na ML S téměř desetiletou zkušeností v oblasti strojového učení a datové vědy je Ke Shen absolventem Kolumbijské univerzity a bývalým Senior Data Scientist ve Walmart Labs. Díky hlubokým odborným znalostem v Pythonu, R, Javě a statistice, uznávaným i mezi kolegy, sdílí ověřené poznatky o tom, jak převést složité AI algoritmy od teorie až k produkční architektuře.
Obsah
Thunderbit · AI agent pro webová data

Extrahuj data z libovolné stránky za 1 kliknutí

Důvěřuje mu více než 250 000 uživatelů
k dispozici bezplatný plán
Z webové stránky do tabulky
Popiš, co potřebuješ — AI agent Thunderbit to nasbírá a exportuje do Excelu, Google Sheets, Airtable nebo Notion. Začni zdarma.
Chrome Store Rating
PRODUCT HUNT#1 Product of the Week