Scrapy נופל הרבה פעמים תחת התיוג של "לא יודע להתמודד עם אתרים מודרניים" רק כי הוא לא מריץ JavaScript. בפועל, זו תפיסה הפוכה לגמרי. עצם העובדה שהוא לא מרנדר את הדף היא כל הרעיון, וברגע שרואים את זה בפעולה, זה כבר לא נראה כמו חוסר ביכולת.
אני הוכחתי את זה לעצמי בהרצה אחת בלבד. בניתי תרחיש בדיקה של קטלוג שמרונדר ב־JavaScript, כיוונתי את Scrapy אל הדף כפי שדפדפן היה מציג אותו, וקיבלתי בחזרה 0 כרטיסי מוצר. אחר כך הפניתי את אותו spider בדיוק לנקודת הקצה של ה־JSON שהדף קרא ברקע, וקיבלתי 8/8 פריטים, נקיים. אותו כלי, אותו סשן, תוצאות הפוכות — והפער בין שני המספרים האלה הוא כל הסיפור של הביקורת הזו.
מה Scrapy באמת עושה — ומה לא

Scrapy הוא מסגרת פייתון לסריקה של אתרים ולחילוץ נתונים מובנים. זו גם ההגדרה של המתחזקים ב-מסמכי הסקירה, ואחרי שעובדים איתו ברור שזה מדויק — בלי קישוטים שיווקיים שצריך לתקן. הוא ותיק ומבוסס מספיק כדי להיות התשובה האוטומטית כשמפתח פייתון שואל במה אנשים רציניים משתמשים כדי לגרד נתונים, וגם המאגר עצמו מגבה את זה: בערך 62,981 כוכבי GitHub נכון ל־2026-07-07 (scrapy/scrapy), עם 11,773 forks ו־590 issues פתוחים באותו יום. רישיון BSD-3-Clause, Python 3.10 ומעלה, והגרסה שבדקתי לעומק הייתה 2.17.0 — שיצאה בדיוק בבוקר שבו הרצתי את הבדיקות, כך שאין כאן כוכבית של "גרסה ישנה".
הקו שמבדיל אותו מהדור החדש של כלים לסריקה מבוססי AI הוא פשוט: Scrapy הוא HTTP בלבד כברירת מחדל. בלי דפדפן. בלי מנוע רינדור. הוא מושך HTML דרך הרשת, מעביר אותו ל־parser, ומאפשר לחלץ שדות בעזרת CSS selectors או XPath. לקרוא לזה מגבלה זה רק חצי נכון, וזה מפספס את עקרון התכנון. ההנחה של Scrapy היא שהרמת Chrome ללא ממשק למשימה שגרתית היא בדרך כלל לא הפתרון הנכון — המסלול החכם יותר הוא למצוא את בקשת הנתונים שהדף כבר מבצע, ולפנות אליה ישירות.
וזו לא פרשנות שלי לכלי. ב-תיעוד התוכן הדינמי הרשמי כתוב זאת במפורש: קודם מאתרים ומשחזרים את בקשת הנתונים הבסיסית, ורק אם אי אפשר לשחזר אותה בצורה נוחה — פונים לדפדפן headless כפתרון חלופי. רוב כלי הגרידה פותחים קודם דפדפן ולא חושבים על ה־API. Scrapy הופך את ברירת המחדל.
יכולות עיקריות, ומה עומד מאחורי כל אחת מהן
מתחת למכסה המנוע, Scrapy מורכב משכבה של רכיבים שכל אחד מהם מניח דבר אחד עליכם: שאתם מפתחים שרוצים שליטה, לא אשף של "קליק אחד וסיימנו".
Spiders. כותבים מחלקה, נותנים לה כתובות התחלה, ומגדירים callback בשם parse שמחזיר פריטים או ממשיך לקישורים נוספים. זה דורש יותר כתיבה מאשר מחלץ no-code — את כל כללי החילוץ אתם מנסחים בעצמכם — אבל בתמורה מקבלים שליטה מדויקת על מה נאסף ולאן הסריקה ממשיכה.
Selectors. השכבה של הפענוח נשענת על parsel, שמבוסס על lxml. גם CSS וגם XPath הם אזרחים מלאים, לא תוספת מאוחרת. הבסיס של lxml הוא הסיבה שהבחירה נשארת מהירה ושקוד החילוץ נראה כמו כוונה ברורה ולא כמו בלגן של חיתוכי מחרוזות.
Feed exports. מכוונים spider לקובץ, ו־Scrapy מסדר את הפריטים ל־JSON, JSON Lines, CSV או XML בלי צורך בתשתית נוספת. בהרצה שלי, spider אחד לקטלוג סטטי כתב גם JSON וגם CSV בלי שכתבתי שורת קוד אחת לייצוא — סיפור ה-feed export אמיתי, והוא עושה בדיוק מה שמבטיחים.
AutoThrottle ובקרות סריקה. הבקשות מתוזמנות באופן אסינכרוני על Twisted, ויש גם מגבלות concurrency, עיכובי הורדה, הגבלות עומק, AutoThrottle להאטה/האצה אדפטיבית, וציות ל־robots.txt. אלה המנגנונים שמונעים מסריקה רחבה להפוך לאירוע שמעמיס על השרת.
HTTP-only, בניסוח אחר כיכולת. בלי דפדפן יש פחות זיכרון, יותר תפוקה, ובלי מנוע רינדור שצריך לתחזק — כל עוד הנתונים שאותם אתם רוצים באמת נגישים דרך HTTP רגיל. ובפועל, הרבה יותר ממה שחובבי "דפדפן תחילה" מניחים, זה בדיוק המצב.
ההתקנה: שרשרת התלויות שאף אחד לא מצלם מסך שלה

ההתקנה הייתה לא-אירוע, וזה דווקא משהו ששווה לומר במפורש על מסגרת בסדר גודל כזה. pip install Scrapy==2.17.0 הסתיים נקי בסביבת וירטואלית חדשה על macOS arm64, הוריד wheels בינאריים, בלי שום ניסיון קומפילציה שנכשל באמצע. אין דרמה לדווח — וזה בדיוק העניין.
אבל תסתכלו על מה ירד יחד איתו. scrapy version -v דיווח על Scrapy 2.17.0 שרץ על lxml 6.1.1, Twisted 26.4.0, pyOpenSSL 26.3.0, ו־cryptography 49.0.0, כש־parsel, cssselect, ו־tldextract משלימים את החבילה. זו באמת טביעת רגל שלמה — שרשרת תלויות של מסגרת סריקה, לא parser קטן של קובץ HTML אחד. על המחשב הזה היו wheels לכל הרכיבים, וההתקנה נשארה חלקה. במערכות אחרות, התיעוד הרשמי עדיין מזהיר מחיכוך תלוי-פלטפורמה, ובאופן היסטורי דווקא cryptography ו־Twisted הם המקומות שבהם זה עלול להיתקע, אז אם אתם עובדים על פלטפורמה חריגה — קחו בחשבון זמן לזה. אצלי ההתקנה עברה חלק; ועדיין, חשוב לדעת מראש מה נכנס למערכת, כי אתם מושכים מסגרת שלמה והיא שוקלת כמו מסגרת שלמה.
שימוש מעשי: מה עמד במבחן

אחרי ההתקנה, המסלול הסטטי עבד חלק. אחזור מלא, בלי הפסדים.
| בדיקה | תוצאה | זמן ריצה |
|---|---|---|
| קטלוג סטטי מקומי + עימוד | 12/12 מוצרים | 0.557s |
| ייצוא CSV לקטלוג סטטי | נכתבו 12 שורות | (אותה הרצה) |
| חילוץ מאמר | כותרת + 3/3 פסקאות גוף | 0.416s |
| גרף סריקה, DEPTH_LIMIT=2 | 11 דפים בעומקים 0/1/2 | 0.904s |
| דף מקומי 500 | סטטוס 500 נתפס, בלי קריסה | 0.424s |
| Books to Scrape (ציבורי) | 20 מוצרים | 2.053s |
| Quotes to Scrape spider (ציבורי) | 12 פריטי ציטוט | 3.465s |
ה־spider של הקטלוג הסטטי עבר עימוד מדף אחד לשני ותפס 12/12 רשומות צפויות, ואז כתב אותן גם כ־JSON וגם כ־CSV באותה הרצה. תרחיש המאמר הוא זה שכדאי להתעכב עליו. Scrapy לא ניסה לנקות אוטומטית את הדף ולהפוך אותו ל־Markdown מסודר — במקום זאת, הוא איפשר לי לכוון שדות article עם selectors מפורשים, ולהפריד טקסט ניווט ו־footer לשדות אחרים. כך קיבלתי 3/3 פסקאות גוף, כשכל הטקסט הסטנדרטי נשאר מבודד ולא התערבב בפלט. זה בדיוק ההסכם: אתם כותבים את ה־selectors, ומקבלים בדיוק מה שביקשתם — ולא יותר.
בקרת הסריקה עמדה יפה גם בקנה מידה קטן. עם DEPTH_LIMIT=2, עיכוב הורדה קצר, concurrency לפי דומיין, ו־robots.txt פעיל, גרף הסריקה עבר על 11 דפים בעומקים 0, 1 ו־2, ומדידת העומק התנהגה כמצופה. גם הטיפול בכשלים היה שקט באותה מידה. דף 500 מכוון חזר כפריט מובנה עם status 500 שנחשף דרך handle_httpstatus_list — בלי exception, בלי ריצה שנפלה. Scrapy מתייחס לסטטוס שגיאה כאל משהו שמטפלים בו בתוך לוגיקת ה־spider, ולא כהפתעה שמפילה את כל הסריקה.
שימוש מעשי: קיר ה־JavaScript והדלת שלידו

ועכשיו לתוצאה שסביבתה נבנתה כל הביקורת הזו.
כיוונתי את ה־HTTP fetcher של Scrapy אל תרחיש בדיקה של קטלוג שמרונדר ב־JavaScript. הוא הוריד את ה־HTML המקורִי, מצא 0 צמתים של .product-card, והמשיך הלאה — כי הוא לא הריץ את הסקריפט שהיה מצייר את הכרטיסים האלה. גם דף ה־JS של Quotes to Scrape הציבורי סיפר את אותו סיפור: 0 צמתי ציטוט מרונדרים. אם היינו עוצרים כאן, היה אפשר לפסול את Scrapy כלא מתאים לשום דבר שנבנה בעשור האחרון.
אבל לא עוצרים כאן. הקטלוג ה־JS הזה אוכלס דרך API של JSON ברקע, כמו ברוב המקרים. הפניתי את אותו spider בדיוק לנקודת הקצה הזו, וקיבלתי 8/8 מוצרים ב־0.416s — בלי דפדפן, בלי רינדור, רק בקשה לכתובת שהדף כבר קרא ממילא וניתוח של ה־JSON שחזר.
ההשוואה הזו ממחישה בקטן את פילוסופיית "שחזור הבקשה". הדף המרונדר הוא הסחת דעת; הנתונים היו שם מאחורי API כל הזמן, והעיצוב של Scrapy דוחף אתכם לפנות אליו ישירות במקום לשלם על דפדפן headless שיישב ויצפה בדף בונה את עצמו. זה מהיר יותר, קל יותר, ושברירי פחות — חוזה API הוא משהו הרבה יותר יציב להישען עליו מאשר ערימת DOM בצד הלקוח. אבל יש כאן מחיר: צריך לעשות את זה ידנית. צריך לפתוח את לשונית הרשת, למצוא את הבקשה, ולשחזר לבד את ה־headers והפרמטרים. Scrapy לא מגלה לכם את ה־API; הוא רק הופך את הפנייה אליו לפשוטה ברגע שמצאתם אותו.
שתי מגבלות, במפורש. כשבאמת אין בקשת בסיס שאפשר לשחזר — כלומר כשהנתונים נבנים לגמרי בצד הלקוח ואין API מאחוריהם — Scrapy צריך שילוב עם דפדפן headless שאתם מחברים בעצמכם, ואני לא בדקתי את המסלול הזה בהרצה הזו. בנוסף, כל מה שתואר כאן רץ על תרחישי בדיקה קטנים ועל דפי דמו ציבוריים. לא הרצתי סריקה של 100 עד 1,000 דפים, אז אין לי טענה לגבי זיכרון, תפוקה או התנהגות retry בהיקף גדול — הליבה האסינכרונית ובקרות הסריקה הן סימן מעודד, אבל סימן הוא לא מדידה.
יתרונות וחסרונות
יתרונות:
- תכנון HTTP בלבד הוא מהיר וקל — אחזור מלא של 12/12 בקטלוג סטטי בכחצי שנייה, 8/8 מ־JSON API ב־0.416s, בלי עומס של דפדפן.
- גישת שחזור הבקשה באמת עובדת: דף JS שהחזיר 0 פריטים, מסר את כל 8 הפריטים דרך ה־API שמאחוריו.
- selectors של CSS ו־XPath, מגובי
lxml, שומרים על קוד החילוץ קריא ומהיר. - ייצוא מובנה ל־JSON/CSV/XML בלי לכתוב תשתית לייצוא.
- טיפול מפורש בשגיאות — 500 חוזר כסטטוס שאפשר לתפוס, לא כקריסה.
- בקרות סריקה בוגרות: concurrency, עיכובים, מגבלות עומק, AutoThrottle, robots.txt.
- רישיון BSD-3-Clause מקל ונוח; התקנה נקייה במכונה עדכנית.
חסרונות:
- לא מרנדר JavaScript by design — דף שמרונדר בצד הלקוח יחזיר 0 צמתים עד שתאתרו את ה־API בעצמכם.
- מציאת הבקשה הבסיסית היא עבודה ידנית; Scrapy לא יכוון אתכם ל־endpoint.
- שרשרת תלויות לא קטנה (Twisted, lxml, cryptography, pyOpenSSL, parsel, tldextract) — כאן זה עבר חלק, אבל היסטורית זו נקודת חיכוך בפלטפורמות חריגות.
- דורש יותר קוד מכלים ללא-קוד או כלי חילוץ אוטומטיים; אתם כותבים ומתחזקים את ה־spiders בעצמכם.
- הבדיקות שלי כיסו תרחישי בדיקה קטנים ואתרי דמו, לא סריקות גדולות — אמינות בקנה מידה עדיין לא הוכחה בהריצה הזו.
למי זה מתאים, ומי עדיף שימשיך הלאה

Scrapy מתאים למפתחים שרוצים שליטה ברמת הקוד וחושבים במונחים של בקשות, לא של דפים. אם התגובה האינסטינקטיבית שלכם לאתר JavaScript איטי היא "יש פה API איפשהו מתחת", הכלי הזה נבנה בדיוק עבור האינטואיציה הזו. הוא מתגמל אנשים שנוח להם לכתוב selectors, לקרוא network tab, ולשלוט בלוגיקת החילוץ מקצה לקצה. עבור אתרים סטטיים, קטלוגים עם עימוד, וכל דבר שמגובה ב־JSON endpoint שאפשר לגלות — הוא מהיר ומדויק.
עדיף לעבור הלאה — או לפחות לשלב אותו עם כלי אחר — אם כתיבה ותחזוקה של spider code היא לא הדרך שבה אתם רוצים לבלות את הזמן, או אם היעדים שלכם מרנדרים את הנתונים שלהם רק בצד הלקוח בלי בקשה שניתן לשחזר, ואתם לא רוצים להוסיף בעצמכם דפדפן headless. ואם החלום היה להדביק כלי ל־URL ולקבל פלט מובנה ונקי בלי לכתוב כללי חילוץ — זה ממילא מעולם לא היה התפקיד של Scrapy, והוא גם לא טען אחרת.
חלופות, ואיפה Thunderbit נכנס לתמונה
נסו את Thunderbit לחילוץ נתוני רשת
כדאי להתחיל ממה שאתם באמת בוחרים: מסגרת חופשית ופתוחת-קוד שאתם מריצים ומתחזקים בעצמכם. אתם מחזיקים את ה־spiders, את שרשרת התלויות, ואת העבודה של איתור בקשת הנתונים של כל אתר. בתמורה אתם לא משלמים על כל בקשה, שומרים הכול בתוך הארגון, ומקבלים שליטה מלאה. עבור הרבה צוותים זו הבחירה הנכונה, והביקורת הזו לא באה לשכנע מישהו לוותר עליה.
נקודת החיכוך נמצאת בבעיית הרינדור והסטייה, והתגובה של Scrapy היא שאתם פותרים אותה: אתם מוצאים את ה־API, משחזרים את הבקשה, ומטפלים במקרה שאין API על ידי חיבור דפדפן בעצמכם. לעומת זאת, API מנוהל לחילוץ נתונים מבוסס AI מוריד את השכבה הזו מהכתפיים שלכם. זה בדיוק המקום שבו Thunderbit יושב עבור קוראים טכניים — API לחילוץ נתונים בעזרת AI יחד עם שרת MCP ו־CLI, לא התוסף לדפדפן שבו משתמשים אנשי מכירות ותפעול. POST /distill הופך דף ל־Markdown נקי ומוכן ל־LLM; POST /extract מחזיר JSON מובנה לפי schema שאתם מגדירים; ושניהם מטפלים ברינדור JavaScript, נגד-בוט ותוכן דינמי בצד השרת — כולל המקרה שמרונדר בצד הלקוח, שבו Scrapy מבקש מכם להשתמש בדפדפן. יש גם שרת MCP לסוכני AI ולעוזרי קוד (עם thunderbit_suggest_fields חינמי כדי למפות שדות לפני שמוציאים שקל), וגם CLI דרך npx @thunderbit/thunderbit-cli לעבודה בטרמינל, ב־CI או ב־cron.
ההבדל הוא לא באיכות, אלא בבעלות. Scrapy הוא מסגרת הנדסית מפורשת: אתם מתחזקים את ה־spider, את ה־pipeline, ואת אסטרטגיית ה־JavaScript, ומקבלים שליטה מלאה ללא עלות לכל קריאה. הסטאק של Thunderbit מעביר את שכבת הרינדור והחילוץ כשירות מנוהל, כך שאתם מדלגים על החפירה ב־network tab ומשלמים לפי קריאה במקום. אם אתם קטנים, עובדים בקוד, ואוהבים להחזיק כל שלב בעצמכם — השליטה של Scrapy היא התאמה טובה יותר. אם אתם צריכים להתרחב על פני מאה אתרים ולא רוצים לשחזר ידנית בקשה לכל אתר — המסלול המנוהל מוריד מכם את כל הקטגוריה הזו של עבודה.
לשדה הרחב יותר, סיכומי הבנצ'מרק האלה מכסים את השכנים: השוואת קוד פתוח מלאה של web scrapers, סקירת Colly כ־crawler Go ללא דפדפן, ו-סקירת Scrapling על selectors אדפטיביים.
מסקנה
אז האם כדאי להשתמש ב־Scrapy? כן — אם אתם מפתחים שרוצים שליטה ומסכימים עם תפיסת העולם: לא לרנדר את הדף, אלא למצוא את הבקשה שמאחוריו. בבדיקות, הפילוסופיה הזו עבדה בדיוק כפי שהובטח. קטלוג JavaScript נתן ל־HTTP fetcher 0 כרטיסים; ה־JSON API שהזין אותו מסר את כל 8 הפריטים לאותו spider. החילוץ הסטטי פגע ב־12/12, selectors למאמרים שמרו על 3/3 פסקאות נקיות מטקסט סטנדרטי, גרף הסריקה כיבד את מגבלת העומק שלו על פני 11 דפים, ו־500 חזר כסטטוס מטופל במקום כקריסה.
אבל צריך לכייל נכון את הטענות. Scrapy לא מרנדר JavaScript, והוא לא ימצא את ה־API בשבילכם — את האינסטינקט הזה אתם צריכים לבנות. שרשרת התלויות היא בגודל של מסגרת אמיתית, ועלולה להכאיב בפלטפורמות מוזרות גם אם כאן היא עברה חלק. וגם, בדקתי תרחישי בדיקה ודפי דמו, לא סריקה של אלף דפים, כך שצריך להתייחס לסיפור של scale כאל דבר מבטיח אך עדיין לא מוכח. בתוך הגבולות האלה, Scrapy הוא הכלי שמקדם בצורה הכי עקבית רעיון כמעט מהפכני בשקט: הדרך המהירה ביותר דרך דף אינטרנט היא בדרך כלל לא דרך הדף עצמו בכלל.
נסו את Thunderbit לחילוץ נתוני רשת Get Started Free
שאלות נפוצות
האם Scrapy יודע לגרד דפים שמרונדרים ב־JavaScript? לא עם ה־HTTP fetcher ברירת המחדל שלו — הוא החזיר 0 צמתים גם בתרחיש JS וגם בדף הציבורי של Quotes JS, כי הוא מוריד HTML בלי להריץ דפדפן. המסלול המיועד הוא למצוא את בקשת הנתונים הבסיסית שהדף מבצע ולפנות אליה ישירות; בבדיקה שלי, ה־JSON API מאחורי קטלוג JS מסר את כל 8 הפריטים. בדפים שאין להם בקשה שניתן לשחזר, צריך לחבר בעצמכם דפדפן headless.
מה בעצם אומר "לשחזר את הבקשה"? רוב הדפים הדינמיים טוענים את הנתונים שלהם מ־JSON API ברקע, ואז מרנדרים אותם בצד הלקוח. במקום להריץ דפדפן כדי לצפות בזה, פותחים את לשונית הרשת, מאתרים את קריאת ה־API, ומכוונים את Scrapy ישירות אליה. זה מהיר ויציב יותר מרינדור — חוזה API נשבר פחות מ־DOM — אבל זו עדיין עבודה ידנית, ו־Scrapy לא יאבחן בשבילכם את ה־endpoint.
האם קשה להתקין את Scrapy?
אצלי ההתקנה הייתה נקייה — pip install Scrapy==2.17.0 הסתיים בלי שגיאות קומפילציה בסביבת venv חדשה על macOS, בעזרת wheels בינאריים. אבל הוא מושך סט גדול יחסית של תלויות (Twisted, lxml, cryptography, pyOpenSSL, parsel, tldextract), והמסמכים הרשמיים עדיין מזהירים מחיכוך תלוי-פלטפורמה במערכות מסוימות, אז כדאי לקחת זאת בחשבון אם אתם על פלטפורמה חריגה.
אילו פורמטי פלט Scrapy תומך בהם? Feed exports מכסים כברירת מחדל JSON, JSON Lines, CSV ו־XML — מכוונים spider לקובץ והוא מסדר את הפריטים בלי קוד נוסף. בהרצה שלי, spider אחד הפיק גם JSON וגם CSV במעבר יחיד. חשוב לציין שהוא מייצא את השדות שבחרתם; הוא לא מנקה אוטומטית דף ל־Markdown.
האם Scrapy חינמי לשימוש מסחרי? כן, הוא תחת BSD-3-Clause — רישיון מקל וידידותי לשימוש מסחרי. כמו תמיד, כדאי לוודא את הרישיון העדכני ב-מאגר לפני שמבנים עליו מוצר, ולשמור על בחירה אחראית של user-agent, proxy ו־rate limit — יכולת לא שווה רשות.


