cheerio לקח 2.9 שניות על עמוד של 10MB ב-Node

עודכן לאחרונה ב-August 19, 2026
cheerio לקח 2.9 שניות על עמוד של 10MB ב-Node
סיכום AI
במכונה אחת, cheerio ב-Node ניתח וחילץ כותרות ו-href מתוך מסמך HTML סינתטי בנפח 10MB בתוך 2,927.89 ms. selectolax, שפעל דרך CPython עם מנתח מבוסס C, השלים את אותו חילוץ שדות בתוך 158 ms. טקסט הכותרות וה-hrefים הממוינים התאימו. זהו ניתוח מקצה לקצה של סטאק בין סביבות ריצה, לא פסק דין מבודד על אלגוריתם של parser. בעמוד של 10KB הפער הוא פי 2, ואף אחד לא יבחין בזה. השאלה האמיתית היא איפה הדפים שלכם יושבים על העקומה הזו. השתמשו ב-cheerio אם אתם ב-Node, ל-API דמוי jQuery יש ערך עבורכם, והעמודים שאתם עובדים איתם דומים לגדלים שנבדקו עד 1MB.

במכונה אחת, cheerio ב-Node ניתח וחילץ כותרות וגם href-ים מתוך מסמך HTML סינתטי בגודל 10 MB בתוך 2,927.89 ms. selectolax, שרץ דרך CPython עם מנתח מבוסס C, השלים את אותה פעולת חילוץ שדות ב-158 ms. טקסט הכותרות והמחרוזות של ה-href-ים, אחרי מיון, תאמו זה לזה. זו השוואה מקצה לקצה בין ערימות ריצה שונות, לא פסיקה מבודדת על אלגוריתם של מנתח כזה או אחר.

בדף של 10 KB הפער הוא פי 2, ואף אחד לא ישים לב. השאלה האמיתית היא איפה הדפים שלכם יושבים על העקומה הזו.

מהו cheerio

cheerio הוא מנתח HTML בסגנון jQuery עבור Node, ובצדק הוא התשובה המובילה באקוסיסטם הזה: 30,449 כוכבי GitHub, רישיון MIT, ודחיפה לריפוזיטורי יום לפני שהרצתי את הבדיקה. גרסה שנבדקה: 1.2.0.

מקור רשמי: המבוא הרשמי של Cheerio.

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();

אם כבר כתבתם jQuery, אתם כבר מכירים את ה-API. ההיכרות הזו היא במידה רבה הסיבה שהוא הצליח כל כך באקוסיסטם שלו.

מתחת למכסה המנוע זה לא מנתח אחד אלא סטאק: htmlparser2 ו-parse5 לניתוח, domhandler ו-domutils לעץ, cheerio-select לבחירת אלמנטים, וגם undici, encoding-sniffer ועוד — 11 תלויות ישירות, שמתורגמות ל-22 חבילות ברמת העליון ו-9.0 MiB על הדיסק. החבילות האלה מספקות יכולות ניתוח וקידוד, וגם מוסיפות לעומס התלויות. הסקירה הזו בדקה פלט על קלט שבור, אבל לא בדקה נכונות קידוד ולא בידדה אף אחד ממנועי הניתוח.

המדידה, ולמה אפשר לסמוך עליה

לבסיס המחקר הזה כבר היה בנצ'מרק למנתחים: חמישה גדלי דפים מ-1 KB עד 10 MB, 50 איטרציות, שלושה סבבים בלתי תלויים, ו—החלק החשוב—שער שוויון שמחשב את ההאש של התוכן שחולץ, כלומר כותרות ממוינות יחד עם href-ים ממוינים, מול מנתח ייחוס. מנתח שמדלג בשקט על עבודה לא יכול להציג זמן מהיר.

הוספת cheerio אליו חייבה שתי בדיקות לפני שסופרים בכלל מספרים.

האם הייחוס נשאר במקום שבו היה קודם? selectolax הורץ שוב באותה סשן ועל אותם פיקסצ'רים. ה-hash של התוכן שלו שוחזר ב-5 מתוך 5 הגדלים, ו-p50 שלו היה בין 0.989× ל-1.079× מהערך שפורסם. כלומר, זו אותה מכונה שהפיקה את הטבלה המקורית.

האם cheerio הפיק את אותם שדות מדורגים? ה-hash של התוכן שלו — שחושב ב-Node לפי אותו כלל, SHA-256 על טקסט כותרות ממוינות ועל href-ים ממוינים — תאם לייחוס ב-5 מתוך 5 הגדלים. זה מוכיח שוויון עבור השדות הממוינים האלה על הפיקסצ'רים הללו, ולא עבור מבנה ה-DOM, סדר המסמך, מאפיינים, נורמליזציית טקסט או שחזור משגיאות.

רק אז הזמנים מתחילים להיות משמעותיים.

גודל דףselectolaxlxmlPyQuerycheerio (Node)cheerio לעומת 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 במילישניות, חציון של שלושה סבבים. parser-bench.json. שלושת מנתחי Python רצו בתהליך אחד; cheerio רץ ב-Node 22, מה שאומר שיש כאן גם גבול של runtime וגם גבול של ספרייה — ראו בהמשך.

איך לקרוא את הטבלה בלי לשקר לעצמכם

Measured results chart: Parser time across page sizes

השורה של 1 KB היא רעש. בין שלושת מנתחי Python הפער בגודל הזה היה 77.6%, והריצות הבודדות חופפות בצורה פראית — selectolax נע בין 0.0267 ל-0.0404 ms בשלוש הריצות שלו. ב-28 מיקרו-שניות, רזולוציית הטיימר ותזמון המערכת שולטות. לא הייתי מדרג שום דבר ב-1 KB, כולל cheerio.

האמצע של הטבלה לא דרמטי. פי 2 עד פי 4 בדפים שבין 10 KB ל-1 MB. עבור סקרייפר שמטפל בכמה מאות דפים, זה 45 מילישניות לדף במקום 15, ולא תראו את זה בכלל.

השורה של 10 MB היא לא רעש. שלוש הריצות של cheerio יצאו ב-2,839, 2,928 ו-2,954 ms — צפופות, ומופרדות היטב משאר השורות. התוצאה מקצה לקצה בגודל 10 MB חורגת בחדות מהדפוס של הגדלים הקטנים יותר. חמישה נקודות גודל לא מספיקות כדי לקבוע סיבוכיות אסימפטוטית או לזהות איזה שכבה — runtime, מנתח, selector, הקצאת זיכרון או garbage collection — גרמה לזינוק.

זה נוחת בטווח של BeautifulSoup. הבנצ'מרק שפורסם מדד עוד ארבעה מנתחים על אותו פיקסצ'ר של 10 MB, ולשים את 2,927.89 ms של cheerio לידם הוא הדבר השימושי ביותר במאמר הזה:

מנתח (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

ארבע השורות של Python הן הערכים שפורסמו מתוך bench_parse.json; הערך של cheerio הוא מהריצה הזו. מנתח הייחוס שוחזר בטווח של 0.989×–1.079× בין שתי הריצות, לכן כדאי להתייחס להבדלים קטנים מכ-8% ככאלה שנמצאים בתוך אי-הוודאות הזו — cheerio מול backend של html.parser ב-BeautifulSoup (פער של 5%) נמצא בתוכה, cheerio מול selectolax (פי 18) לא.

BeautifulSoup היא הספרייה שאנשים פונים אליה כשהם רוצים נוחות ומודעים לכך שהיא איטית — זו הספרייה שכל דיון על ביצועי Python אומר לכם להחליף. במסמך של 10 MB, cheerio יושב בתחתית אותו טווח, ולא בטווח של המנתחים שמבוססים על C שאיתם נוטים לשייך אותו.

שאלת ההחלפה בצד Node נשארת פתוחה במאמר הזה. חלופות חדשות יותר ל-Node לא נבדקו, ולכן התוצאה לא יכולה לטעון שהחלפת ספריות היא בלתי אפשרית או לבטל אותן כפחות מבוססות. היא רק מראה את המסלול שנמדד של cheerio מול הסטאקים של Python שצוינו.

זו גם השוואת runtime, לא רק ספרייה. המילישניות של cheerio מגיעות מ-JIT ומ-garbage collector של Node; האחרות מגיעות מ-CPython שקורא למנתחים מבוססי C. ה-hash של התוכן מוכיח שנעשתה אותה עבודה, ושני המספרים הם מה שמפתח שבוחר סטאק באמת חווה — אבל אף אחד לא צריך לקרוא מזה ש"האלגוריתם של cheerio גרוע פי 18 משל selectolax". זה מה שקרה, על המכונה הזו, בתוך ה-runtime הטבעי של כל ספרייה.

מציאות ההתקנה

ספרייהחבילותנפח דיסקרישיוןכוכביםpush אחרון
cheerio22 (npm)9.0 MiBMIT30,4492026-08-11
PyQuery3 (pip)20.1 MiBBSD2,3802026-07-27

מקור רשמי: תיעוד ההגדרות של Cheerio.

metadata-snapshot.json, נשלף ביום הכתיבה.

npm install cheerio לקח פחות משתי שניות והוריד 9.0 MiB. טעינה קרה נמדדה ב-0.056 שניות בהרצת המרה נפרדת על אותה מכונה.

אחת-עשרה תלויות ישירות זה הרבה עבור מנתח, וחשוב לדעת זאת אם אתם מבצעים audit לעץ התלויות שלכם: htmlparser2, parse5, parse5-htmlparser2-tree-adapter, parse5-parser-stream, domhandler, domutils, dom-serializer, cheerio-select, encoding-sniffer, undici ו-whatwg-mimetype. שתי מימושי ניתוח מלאים מגיעים שם יחד, כי cheerio יכול להשתמש בכל אחד מהם לפי מה שמבקשים ממנו.

שלושים אלף כוכבים ודחיפה יום לפני הבדיקה הם סימן תחזוקה טוב מאוד בקטגוריה הזו.

זיכרון, ומה HTML שבור עושה לו

טביעת הזיכרון והתנהגות מול קלט שבור משפיעות על פריסה ועל טיפול בכשלים, ולכן שתיהן נמדדות כאן בנפרד.

ההקשר הרחב יותר של מבחן העומס מופיע ב-השוואת הזיכרון וה-HTML השבור בין עשר ספריות.

זיכרון תהליך שיא, באמצעות /usr/bin/time -l, תהליך חדש לכל תא — רצפת ה-import היא מה שהספרייה צורכת כשהיא נטענת ונשארת סרק, והשיאים כוללים את המסמך.

ספרייהruntimeרצפת importשיא 226 KBשיא 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 ו-Node אינם ברי-השוואה ישירה זה לזה; המפרש נמצא בתוך שניהם.

ל-cheerio יש את רצפת ה-import הגבוהה ביותר בטבלה המשולבת הזו — 66.8 MiB, כולל runtime של Node והתלויות. התהליך שלו הגיע לשיא של 398.5 MiB בפיקסצ'ר של 10 MB. השורות האחרות כוללות מנתחים, ממירים ומחלצי מאמרים שעושים עבודה ראשית שונה, ולכן צריך להשתמש בהן כהקשר של footprint תהליכי ולא כדירוגי ביצועים בין שווים. השורה של turndown באותו runtime הגיעה לשיא גבוה יותר, אבל היא מבצעת המרה ולא את חוזה חילוץ הכותרות וה-href-ים שנמדד עבור cheerio.

HTML שבור. שנים-עשר מסמכים, שכל אחד מהם שבר דבר אחד בדיוק — תגיות לא סגורות, רכיבי inline מקוננים לא נכון, מאפיינים בלי מירכאות עם רווחים, סוגרים זרים, בלי <html> בכלל, מאפיינים כפולים, מסמך שנחתך באמצע תג, ישויות פגומות, <script> לא סגור, הצהרת charset שקרית, הערה שמכילה markup, ו-600 רמות של קינון — ועוד שני בקרות תקינות בגודל תואם, כי "הוא לא החזיר כלום" אומר משהו על תקינות שבורה רק אם הספרייה גם שותקת על מסמך נקי באותו גודל.

cheerio זרק שגיאה ב-0 מתוך 14 ולא החזיר כלום ב-0, ושיחזר 11/22 סנטינלים מדורגים על פני הפיקסצ'רים השבורים (malformed-results.json). עבור מנתחים, המדורג בודק סנטינלים של כותרות וקישורים לאורך אחד-עשר מסמכים שבורים שניתן לדרג; הוא לא מדרג את סנטינל הפסקה, והפיקסצ'ר של <script> לא סגור מוחרג. בלי baseline באותו חוזה בחלק הזה, 11/22 הוא לא דירוג איכות. המסקנה הנתמכת היא ש-cheerio החזיר פלט לא ריק בלי לזרוק שגיאה על כל ארבע-עשרה הקלטים השבורים-פלוס-בקרה, ובמקביל שיחזר חצי מהסמנים המדורגים.

יתרונות וחסרונות

לזכותו. תחביר jQuery מוכר. MIT. אות תחזוקה מתוזמן של 30,449 כוכבים ופעילות ריפוזיטורי ביום שלפני הבדיקה. קיימים שני backends לניתוח וחבילות הקשורות לקידוד, אם כי שחזור backend ונכונות קידוד לא בודדו כאן. ה-hash של הכותרות וה-href-ים הממוינים תאם לייחוס בכל גודל פיקסצ'ר.

נגדו. איטי פי 18.5 מ-selectolax על מסמך של 10 MB, ופי 4 על 1 MB. אחת-עשרה תלויות ישירות, כולל שני מימושי ניתוח מלאים. רק Node. ושום דבר בתיעוד שלו לא רומז על גודל שבו הוא מפסיק להיות הבחירה הברורה.

מי צריך להשתמש בו, ומי לא

השתמשו ב-cheerio אם אתם ב-Node, ממשק בסגנון jQuery חשוב לכם, והדפים שאתם עובדים איתם דומים בגדלים שנבדקו עד 1 MB. מגה-בייט אחד הוא הנקודה הגדולה ביותר שנבדקה לפני הזינוק החד של 10 MB; המאמר הזה לא קובע את נקודת החיתוך ביניהם ולא טוען כמה מהאינטרנט נמצא מתחתיה.

בצעו בנצ'מרק לפני השימוש במסמכי HTML גדולים מאוד כמו דוחות שנוצרים אוטומטית, דמפי קטלוגים או דפי רשימות ארוכים. התנהגות מול XML sitemap לא נבדקה. על פיקסצ'ר ה-HTML של 10 MB, 2.9 שניות למסמך הן עלות ממשית שמצטברת.

אם אתם ב-Python, ההשוואה הזו אומרת משהו אחר: selectolax, lxml ו-PyQuery למעשה שווי-ביצועים מ-10 KB ומעלה (בתוך 0.5% עד 5.4%, עם טווחי ריצה חופפים), ולכן כדאי לבחור לפי API ולא לפי מהירות. הפער של cheerio מול שלושתם הוא המספר המעניין, לא ההבדלים ביניהם.

איפה נכנס API מנוהל

cheerio מנתח HTML שכבר יש לכם. הוא לא מבצע fetch, לא מרנדר JavaScript, ולא מתמודד עם שכבת anti-bot — ובמטרות אמיתיות רבות, זה החלק הקשה יותר של העבודה.

שירות מנוהל של fetch/render/extraction, כולל Thunderbit שלנו, יושב בנקודת אחריות אחרת. Thunderbit לא נבחן כאן. ההבחנה הרלוונטית היא בין ניתוח HTML שסופק לכם עם selectors לבין מיקור-חוץ של איסוף, רינדור וחילוץ; המאמר הזה לא מספק השוואת איכות, זמן תגובה או עלות על אותו מדד.

הניסוח ההוגן: אם ה-HTML כבר אצלכם ואתם יודעים את ה-selectors, cheerio הוא חינמי ונעים לשימוש. אם אתם מבצעים איסוף דפים בקנה מידה גדול, או מעדיפים לתאר את הנתונים ולא את ה-DOM, זו כבר רכישה אחרת.

לשדה הרחב יותר, סקירת ה-web scraping APIs שלנו סוקרת פתרונות מתארחים, ו-עמוד העוגן של הסקרייפרים בקוד פתוח עוסק במאוכסנים עצמאית. אם הפלט המנותח מיועד למודל, המרת HTML ל-Markdown ב-Python מסבירה איפה הולכת לאיבוד fidelity.

נסו את Thunderbit לחילוץ נתוני רשת

האם כדאי להשתמש ב-cheerio?

כן, ב-Node, כשהתאמת ה-API חשובה והמסמכים הייצוגיים נשארים קרובים לטווח הקטן עד 1 MB שנבדק.

ההיכרות עם ה-API וסימני התחזוקה הנוכחיים הם שיקולים לגיטימיים לבחירה. הבנצ'מרק לא מוכיח שקיימת תשובת תמיכה מסוימת, ולא שגודל הדפים שנבדק מייצג את הטווח בייצור.

המספר שצריך לזכור הוא זה של 10 MB. איפשהו בין 1 MB ל-10 MB, העלות של cheerio מפסיקה לעקוב אחרי האחרים ומתחילה להתרחב — פי 4 הופך לפי 18.5. אם הקורפוס שלכם כולל מסמכים כאלה, תריצו בנצ'מרק לפני שאתם מתחייבים, כי שום דבר בספרייה לא יזהיר אתכם.

נסו את Thunderbit לחילוץ נתוני רשת Get Started Free

שאלות נפוצות

האם הוגן להשוות את cheerio מול מנתחי Python?
זו השוואת סטאק, לא השוואת אלגוריתם. כל ארבעת הכלים הפיקו טקסט כותרות ו-href-ים זהים תחת כלל ה-hash ב-5 מתוך 5 גדלי דפים. זה לא מוכיח שקילות מלאה של המנתחים. הזמנים של cheerio כוללים את התנהגות ה-runtime של Node, בעוד האחרים כוללים את CPython שקורא למנתחים מבוססי C; ההשוואה מתארת את הבחירות האלה מקצה לקצה.

למה השורה של 1 KB לא מדורגת?
כי ב-28 מיקרו-שניות המדידה נשלטת על ידי רעש. לאורך שלוש הריצות, מנתחי Python התפזרו ב-77.6%, עם חפיפה בין ריצות בודדות. כל סדר בגודל הזה יהיה תוצר לוואי. מ-10 KB ומעלה הקריאה יציבה מספיק.

מה גורם לזינוק ב-10 MB?
הבדיקה הזו לא אומרת. מה שהיא כן קובעת הוא שהזינוק אמיתי ולא רעש: שלוש הריצות של cheerio נחתו ב-2,839, 2,928 ו-2,954 ms, מופרדות היטב מכל השאר, בעוד הפער ב-1 MB היה פי 4. בידוד הסיבה היה דורש profiling נפרד של ה-backends של המנתח, וזה היה מחוץ להיקף כאן.

כמה תלויות באמת יש לו?
אחת-עשרה ישירות, 22 ברמה העליונה לאחר פתרון, ו-9.0 MiB על הדיסק. שתיים מהן הן מימושי ניתוח מלאים — htmlparser2 ו-parse5 — כי cheerio יכול להשתמש בכל אחד מהם. זה המחיר של תמיכה גם בניתוח סלחני וגם בניתוח תואם-מפרט, וחשוב לדעת זאת אם אתם מבצעים audit לעצי תלויות.

מה לא נבדק כאן?
הבדיקות כיסו שיא זיכרון תהליך על מסמך אחד של 226 KB ועל מסמך אחד של 10 MB, ועוד סט של 14 קלטים שבורים-פלוס-בקרה שבו cheerio לא זרק שגיאה על אף אחד, החזיר פלט לא ריק על כולם, ושיחזר 11/22 סנטינלים מדורגים. לא נבדקו streaming דרך parse5-parser-stream, נכונות קידוד, שחזור ספציפי ל-backend, מיקום קפיצת הביצועים בין 1 ל-10 MB, ניתוח XML, או חלופות חדשות יותר ל-Node.

Ke
Ke
CTO ב-Thunderbit | מדען נתונים בכיר ומומחה ב-ML עם כמעט עשור של ניסיון בלמידת מכונה ובמדע הנתונים, קה שן הוא בוגר אוניברסיטת קולומביה ולשעבר מדען נתונים בכיר ב-Walmart Labs. עם מומחיות עמוקה ומוכרת בקרב עמיתים ב-Python, R, Java וסטטיסטיקה, הוא משתף תובנות מוכחות-בקרב על המעבר מאלגוריתמי AI מורכבים מתיאוריה לארכיטקטורה ברמת production.
תוכן עניינים
Thunderbit · סוכן נתוני אינטרנט מבוסס AI

חלץ נתונים מכל דף בתוך קליק אחד

למעלה מ-250,000 משתמשים סומכים עליו
יש תוכנית חינמית
מדף אינטרנט לגיליון נתונים
תארו מה אתם צריכים — סוכן ה-AI של Thunderbit מחלץ את זה ומייצא ל-Excel, Google Sheets, Airtable או Notion. חינמי להתחלה.
Chrome Store Rating
PRODUCT HUNT#1 Product of the Week