למה אתר כמו אגד הוא לא עוד יעד סקראפינג פשוט

הטעות הראשונה שמהנדסים עושים היא להתייחס לאתר אגד כמו אל אתר תוכן. הם שולחים בקשת GET, מקבלים HTML ומתחילים לפרסר. זה נכשל מיד. חיפוש קו אוטובוס הוא לא לינק, הוא טופס אינטראקטיבי שמפעיל שרשרת של אירועי JavaScript. בחירת מוצא, יעד ותאריך מפעילה קריאות AJAX ברקע, מעדכנת את ה-DOM, ומנהלת state בצד הלקוח. אם תנסו לדלג על השלבים האלה ולגשת ישירות ל-URL של התוצאות, תקבלו דף ריק או שגיאה.

זו הסיבה שכלים כמו Playwright או Puppeteer הם נקודת הפתיחה, לא אופציה. אנחנו צריכים לדמות משתמש אמיתי: להקליד בתיבות טקסט, ללחוץ על כפתורים, להמתין לאלמנטים שיופיעו באופן אסינכרוני. כל ניסיון לחסוך פה במשאבים ולהישאר בסביבת HTTP טהורה יוביל לשעות של תסכול. לדוגמה, ראיתי פרויקטים שניסו להנדס לאחור את קריאות ה-API הפנימיות של האתר. זה עבד שבועיים, עד העדכון הבא של ה-frontend ששינה את ה-endpoint או את ה-payload הנדרש והשבית את כל המערכת. התחזוקה של גישה כזו גבוהה משמעותית מהשקעה ראשונית בבניית סקריפט מבוסס browser automation. המטרה היא לא רק להוציא את הנתונים פעם אחת, אלא לבנות תהליך עמיד שישרוד את השינויים הבלתי נמנעים באתר היעד.

איסוף קטלוג וניטור מחירים: הגישה הנכונה

אחד ה-use cases המרכזיים הוא איסוף קטלוג אגד – כלומר, מיפוי כל קווי הנסיעה האפשריים. זה לא פשוט כמו לעקוב אחרי לינקים של 'העמוד הבא'. צריך לייצר באופן פרוגרמטי את כל הצירופים של מוצא ויעד רלוונטיים. זה יכול להגיע בקלות לעשרות אלפי חיפושים שונים רק כדי לכסות את הרשת הארצית. לאחר מכן, עבור כל קו, נרצה לבצע ניטור מחירים אגד לאורך זמן.

התהליך חייב להיות מבוסס אינטראקציה. הסקריפט יצטרך לבצע לולאה שבה הוא:

  1. מנווט לדף החיפוש הראשי.
  2. ממלא את שדות המוצא והיעד.
  3. בוחר תאריך מה-date picker (אלמנט JS קלאסי).
  4. לוחץ על כפתור החיפוש וממתין לטעינת התוצאות.
  5. מחלץ את הנתונים הנדרשים כמו מחירים וזמני יציאה.

האתגר הוא לעשות זאת ביעילות. הרצת אלפי מופעי דפדפן במקביל דורשת תכנון. צריך להשתמש ב-pools של workers ולנהל תורים. חשוב למדוד זמני תגובה – אם חיפוש ממוצע לוקח 4 שניות, אז סריקה של 10,000 קווים תיקח מעל 11 שעות על worker בודד. זה לא סקיילבילי. לכן, הפעלה מקבילית היא הכרח. כמו כן, חשוב לטפל בשגיאות נקודתית. אם חיפוש אחד נכשל, הוא לא אמור להפיל את כל הריצה. מנגנון retry חכם, אולי עם שימוש ב-proxy אחר, הוא קריטי כדי להגיע לאחוזי הצלחה של מעל 99% באיסוף הנתונים. המדריך שלנו על טיפול בשגיאות רשת נפוצות יכול לתת כאן בסיס טוב.

מעקב זמינות מושבים: אתגר ה-Real-Time

אם ניטור מחירים הוא מורכב, מעקב מלאי/זמינות אגד הוא סדר גודל אחר של קושי. כאן אנחנו מתמודדים עם נתונים שמשתנים לא פעם ביום, אלא פעם בדקה. זמינות המושבים בקו מבוקש יכולה להשתנות בזמן שה-scraper שלנו עדיין רץ. זהו failure scenario קלאסי: ה-scraper מדווח על 5 מושבים פנויים, אבל בזמן שעבר מהרצת הסקריפט ועד שהמידע נצרך, כל הכרטיסים נמכרו. המידע הופך לחסר ערך.

כדי להתמודד עם זה, צריך לעבור ממודל של סריקות תקופתיות (batch) למודל שקרוב יותר לזמן אמת. זה דורש תשתית מהירה מאוד, עם latency נמוך בין ה-worker לאתר היעד. כל שנייה חשובה. בנוסף, התהליך עצמו מורכב יותר. אחרי קבלת תוצאות החיפוש הראשוניות, לעיתים קרובות צריך לבצע פעולה נוספת – 'בחר נסיעה' – כדי לראות את מפת המושבים או את הכמות המדויקת של המקומות הפנויים. זה מוסיף עוד שלב לתהליך, עוד אינטראקציית JS, ועוד נקודת כשל אפשרית. ניהול סשנים הופך לקריטי. האם האתר משתמש בקוקיות כדי לזכור את החיפוש שבחרת? כנראה שכן. לכן, כל סדרת הפעולות (חיפוש -> בחירה -> בדיקת זמינות) צריכה להתבצע באותו קונטקסט דפדפן. אי אפשר לפצל את המשימות האלה בין workers שונים בלי לנהל את הסשן בקפידה. המפתח הוא לבנות 'טרנזקציות' קצרות וממוקדות שבודקות זמינות לקו ספציפי וחוזר חלילה, במקום סריקות ארוכות וגורפות.

איפה הגישה הזו נכשלת (ולמה לא תמיד צריך Headless Browser)

אחרי כל מה שאמרתי על Playwright, חשוב לשים סייג. להריץ דפדפן מלא זה יקר מבחינת CPU ו-RAM. אם כל מה שאתם צריכים זה רשימה של כל תחנות האוטובוס של אגד בארץ, ייתכן שהמידע הזה קיים בעמוד סטטי או נטען מקריאת API פשוטה וגלויה. במקרה כזה, להפעיל Playwright זה כמו להשתמש בפטיש 5 קילו כדי לתקוע נעץ. זה בזבוז משאבים.

לפני שכותבים שורת קוד אחת של browser automation, השלב הראשון הוא תמיד לפתוח את ה-DevTools ולנתח את תעבורת הרשת. חפשו קריאות ל-/api/ או קבצי JSON שנטענים ברקע. לפעמים, אפשר למצוא endpoint שמחזיר בדיוק את המידע שצריך, בלי כל התקורה של ה-UI. אם תצליחו למצוא API כזה, תוכלו לבנות API / קובץ נתונים אגד בעצמכם, באמצעות בקשות HTTP פשוטות. זה יהיה מהיר ואמין פי 100 מכל סקריפט אוטומציה. הבעיה היא שה-APIs האלה לא מתועדים, הם יכולים להשתנות ללא הודעה מוקדמת, ולעיתים דורשים headers מיוחדים או טוקנים שנוצרים על ידי ה-JavaScript של האתר. לכן, זו גישה שמתאימה יותר למשימות ספציפיות ומוגדרות היטב. למידע נוסף על התהליך, תוכלו לקרוא את המדריך שלנו להנדוס לאחור של APIs.

בניית Data Pipeline אמין למודיעין תחרותי

איסוף הנתונים הוא רק חצי מהסיפור. כדי להפוך את המידע הזה לבעל ערך, למשל עבור מודיעין מתחרים אגד, הוא חייב להיות עקבי, אמין וזמין. זה אומר לבנות data pipeline מלא. ה-scraper הוא רק השלב הראשון.

הנתונים הגולמיים שחולצו צריכים לעבור ניקוי וסטנדרטיזציה. לדוגמה, שמות תחנות עשויים להופיע בוריאציות שונות. לאחר מכן, הנתונים המנוקים נשמרים בבסיס נתונים – בין אם זה PostgreSQL, MongoDB או מחסן נתונים ייעודי. משם, אפשר לבנות דשבורדים, להפיק התראות על שינויים משמעותיים (כמו קו חדש שנוסף), או לייצא את המידע לפורמט CSV או API לשימוש מערכות אחרות. דמיינו מערכת שמנטרת 300 קווים מרכזיים, 4 פעמים ביום, ומייצרת מעל 1,200 נקודות נתונים חדשות מדי יום על מחירים וזמינות. זה דורש אוטומציה מלאה.

בנוסף, התשתית עצמה צריכה להיות חסינה. מה קורה אם ה-IP של השרת שלכם נחסם? כאן נכנסת לתמונה רוטציית פרוקסי חכמה. שימוש ב-pool של פרוקסי מסוג residential יכול להפחית משמעותית את הסיכוי לחסימה. צריך גם מערכת ניטור שתתריע אם אחוז השגיאות עולה מעל סף מסוים (למשל, 5%), מה שיכול להצביע על שינוי במבנה האתר או על הפעלת מנגנון הגנה חדש. בניית פייפליין כזה היא השקעה משמעותית, אבל היא ההבדל בין פרויקט scraping חד-פעמי ושברירי לבין נכס דאטה אסטרטגי.