למה Requests פשוט לא יספיק ל-2Eat
בואו נשים את זה על השולחן: אם הגישה הראשונית שלכם ל-2Eat היא עם requests או curl, אתם בדרך לכאב ראש. האתר אולי נראה סטטי, אבל רוב התוכן החשוב — תפריטים, זמינות, מבצעים — נטען ומרנדר דינמית באמצעות JavaScript. שליחת בקשת GET פשוטה ל-URL של מסעדה תחזיר לכם שלד HTML, לא את התפריט המלא. זה הכשל הראשון והנפוץ ביותר.
כדי לבצע איסוף קטלוג 2Eat בצורה אמינה, אתם חייבים להריץ דפדפן אמיתי. תפסיקו עם Selenium לפרויקטים חדשים. Playwright מנצח אותו ב-2025 בכל מטריקה רלוונטית, במיוחד בביצועים וב-API האסינכרוני שלו. הוא מאפשר לחכות לאלמנטים ספציפיים שמופיעים רק אחרי שה-JS סיים לרוץ, לדמות אינטראקציות משתמש כמו גלילה כדי לטעון עוד תוצאות, ולהבטיח שה-HTML שאתם מנתחים הוא מה שהמשתמש באמת רואה. ראינו שיפור של 30% בזמן הריצה הממוצע במעבר מ-Selenium ל-Playwright בפרויקטים דומים.
האתגר הוא לא רק לקבל את ה-HTML. הוא לקבל את ה-HTML הנכון. ללא רינדור מלא, אתם תפספסו שדות קריטיים כמו מבצעים שמופיעים כבאנרים דינמיים או זמינות של משלוחים שמתעדכנת בזמן אמת. הניסיון לנתח את קריאות ה-API הפנימיות של האתר הוא אפשרי, אבל שביר מאוד. הם יכולים לשנות את ה-endpoints מחר בבוקר בלי אזהרה, וה-scraper שלכם יישבר. דפדפן אמיתי, שמנוהל נכון, הוא הדרך היחידה להשיג יציבות. אם אתם חדשים בתחום, כדאי להתחיל עם מדריך Playwright stealth כדי להבין את הבסיס.
ניהול State ופרוקסי: האתגרים הנסתרים
אוקיי, אז השתכנעתם להשתמש ב-Playwright. הבעיה הבאה שתתקלו בה היא לא חסימת IP ישירה, אלא תוכן לא רלוונטי. 2Eat, כמו כל פלטפורמת משלוחים, מתאימה את עצמה למשתמש. התוכן שתראו תלוי במיקום הגיאוגרפי, בהיסטוריית החיפושים ואפילו בשעה ביום. אם תשלחו בקשות מ-IP של דאטה סנטר באירלנד, תקבלו תוצאות שלא מייצגות את השוק הישראלי. זה קריטי במיוחד למימוש use case של מודיעין מתחרים 2Eat.
הפתרון הוא proxy rotation, אבל לא סתם. אתם צריכים רשת של residential proxies ישראליים. זה לא נתון למשא ומתן. שימוש בפרוקסי מחו"ל יזהם לכם את הדאטה. הנקודה החשובה יותר היא ניהול session. אל תחליפו IP בכל בקשה. זה דפוס התנהגות חשוד שמפעיל מנגנוני הגנה. במקום זאת, השתמשו ב-sticky sessions: החזיקו את אותו ה-IP למשך סשן שלם של איסוף נתונים ממסעדה אחת או מאזור מסוים (למשל, 5-10 דקות). זה מדמה התנהגות אנושית ומפחית את הסיכוי לחסימה.
ניהול state לא נגמר ב-IP. שמרו קוקיז ו-local storage בין בקשות באותו סשן. זה עוזר לשמור על הקונטקסט שהאתר בנה סביבכם (למשל, כתובת שהזנתם למשלוח) ומבטיח שהנתונים על זמינות וזמני משלוח יהיו מדויקים. המטרה היא לא להיראות כמו 10,000 משתמשים חדשים כל שנייה, אלא כמו 100 משתמשים חוזרים שגולשים באתר בצורה הגיונית. להבנה עמוקה יותר של בחירת הרשת הנכונה, קראו את המדריך על איך לבחור פרוקסי residential.
איך לבנות Data Pipeline ל-2Eat שעומד בעומס
איסוף הנתונים הוא רק ההתחלה. השלב הבא הוא לבנות תהליך יציב שיכול לרוץ 24/7. המטרה היא לא רק להריץ את ה-scraper, אלא להפוך את הפלט שלו למוצר נתונים שמיש, כלומר לספק API / קובץ נתונים 2Eat מעודכן באופן קבוע. פרויקט כזה דורש ארכיטקטורה מבוזרת.
אל תריצו את ה-scraper מהמחשב שלכם או משרת בודד. השתמשו בתור עבודות (message queue) כמו RabbitMQ או Redis. כל משימה בתור מייצגת URL שצריך לסרוק (למשל, דף קטגוריה או דף מסעדה). בצד השני, יהיו לכם מספר workers (יכולים להיות קונטיינרים של Docker) ששולפים משימות מהתור, מריצים אינסטנס של Playwright, אוספים את הדאטה, ומאחסנים אותו בבסיס נתונים מרכזי כמו PostgreSQL או MongoDB.
הגישה הזו נותנת לכם סקיילביליות. צריכים לסרוק מהר יותר? פשוט תוסיפו עוד workers. אחד ה-workers נפל? התור שומר את המשימה והיא תטופל על ידי worker אחר. זה גם מאפשר לכם לנהל קצבי בקשות בצורה חכמה. אתם יכולים להגביל את קצב שליפת המשימות מהתור כדי לא להפציץ את 2Eat. במערכת שבנינו, אנחנו מכוונים לקצב של לא יותר מ-30-40 דפים בדקה פר IP, עם מרווחים אקראיים בין בקשות, כדי לשמור על פרופיל נמוך. זה מאפשר לנו להגיע ל-98% הצלחה באיסוף, עם latency ממוצע של 4-6 שניות לדף שעובר רינדור מלא.
Failure Scenario: מלכודת המחירים הדינמיים
הנה תרחיש שראיתי קורה יותר מפעם אחת בפרויקטים של ניטור מחירים 2Eat: ה-scraper עובד מצוין, הנתונים נאספים, אבל הם פשוט לא נכונים. הסיבה? מבצעים ושינויי מחיר שתלויים באינטראקציה של המשתמש.
דמיינו מסעדה שמציעה "מבצע 1+1 על הפיצה השנייה". ה-scraper שלכם טוען את הדף ורואה את המחיר הרגיל של פיצה אחת. הוא לא רואה את ההנחה כי היא מופעלת רק אחרי שהמשתמש מוסיף פריט שני לסל. ה-scraper שלכם, שמתוכנת רק לקרוא מידע מהתפריט, מדווח על המחיר הלא נכון. זהו כשל שקט ומסוכן, כי הוא לא מייצר שגיאה. הוא פשוט מזהם את הדאטה שלכם בשקט.
כשל נוסף הוא "דמי משלוח דינמיים". המחיר משתנה לפי הכתובת, השעה, ומזג האוויר. אם ה-scraper שלכם לא מדמה הזנת כתובת ספציפית, הוא יקבל מחיר ברירת מחדל או שלא יקבל מחיר בכלל. כדי להתמודד עם זה, ה-scraper חייב להיות מתוחכם יותר. הוא צריך לדמות תהליך הזמנה מלא: לבחור כתובת, להוסיף פריטים לסל, להגיע לדף הצ'קאאוט, ורק שם לקרוא את המחיר הסופי. זה מסבך את הלוגיקה פי עשרה, דורש ניהול סשנים קפדני ומוסיף המון נקודות כשל אפשריות. זו אחת הסיבות שבגללן טיפול בשגיאות 429 והתנהגויות בלתי צפויות של האתר הוא קריטי. אי אפשר פשוט לקוות לטוב.
מתי לא כדאי לבנות Scraper כזה לבד
למרות כל מה שכתבתי, יש מצבים שבהם בניית scraper מותאם אישית ל-2Eat היא לא הדרך הנכונה. חשוב להיות כנים לגבי זה. פרויקט כזה הוא לא משהו שעושים בסוף שבוע. הוא דורש תחזוקה מתמדת.
האתר של 2Eat ישתנה. סלקטורים של CSS יישברו, מבנה ה-HTML ישתנה, ולפעמים הם יוסיפו מנגנוני הגנה חדשים. אם אין לכם צוות הנדסי שיכול להקדיש לפחות 10-15 שעות שבועיות לתחזוקה, ניטור, ותיקון ה-scraper, הוא יהפוך מהר מאוד ללא רלוונטי. הנתונים יתחילו להיכשל, בהתחלה בקטנה ואז בקריסה מלאה. זה לא פרויקט של "שגר ושכח".
בנוסף, אם אתם צריכים נתונים היסטוריים או דורשים כיסוי של כל הקטלוג (שכולל אלפי מסעדות ועשרות אלפי פריטים) מהיום הראשון, המאמץ ההנדסי הראשוני הוא עצום. זה לא רק כתיבת הקוד, אלא בניית כל התשתית מסביב: ניהול פרוקסי, בסיסי נתונים, מערכת ניטור והתראות. אם הצורך שלכם הוא בנתונים נקודתיים או בפרויקט חד-פעמי, ייתכן שהשקעת הזמן והמשאבים בבניית מערכת כזו מאפס לא תהיה מוצדקת. במקרים כאלה, כדאי לשקול פתרונות אחרים לפני שצוללים לפיתוח של חודשים. המטרה היא לקבל תובנות מהנתונים, לא רק לבנות כלי לאיסוף שלהם.
