למה Requests לבד לא יספיק פה
הטעות הראשונה שראיתי יותר מדי פעמים היא לגשת לאתר כמו מאוחדת עם ספריית HTTP פשוטה. אתה מריץ curl או requests על ה-URL הראשי, מקבל HTML, אבל כל התוכן הדינמי חסר. אין רשימות רופאים, אין פרטי שירותים, כלום. הסיבה היא שה-HTML הראשוני הוא רק מעטפת (shell). הדאטה האמיתי נטען אסינכרונית דרך קריאות XHR/Fetch ל-API פנימי אחרי שה-JavaScript רץ בדפדפן.
הגישה הנכונה מתחילה ב-DevTools, לא ב-IDE. פתח את לשונית ה-Network ותראה את התקשורת האמיתית. תזהה במהירות את ה-endpoints שמחזירים את המידע שאתה צריך, כנראה בפורמט JSON. זה מפתה לנסות ולחקות את הקריאות האלה ישירות. לפעמים זה עובד, אבל בדרך כלל יש תלות ב-headers, עוגיות סשן, או טוקנים (כמו CSRF או JWT) שהדף מייצר. ניסיון לזייף את כל אלה ידנית הוא שביר ודורש תחזוקה גבוהה. לכן, לרוב הפרויקטים של איסוף קטלוג מאוחדת, אני ממליץ להתחיל עם כלי שמריץ דפדפן אמיתי. תפסיקו עם Selenium לפרויקטים חדשים. Playwright מנצח אותו ב-2025 בכל מטריקה רלוונטית, במיוחד במהירות וביכולות ה-network interception שלו.
איסוף קטלוג שירותים ומעקב זמינות רופאים
אחד ה-use cases המרכזיים הוא בניית תמונה מלאה של היצע השירותים והצוות הרפואי. זה יכול לכלול מיפוי של כל הרופאים, התמחויותיהם, והמרפאות בהן הם מקבלים. מדובר על קטלוג שיכול להגיע לאלפי ישויות (רופאים, שירותים, מרפאות), ולכן תהליך ה-scraping חייב להיות אוטומטי ויעיל. המטרה היא לחלץ שדות כמו שמות מוצרים/מודעות (במקרה הזה, שמות רופאים או שירותים) וחשוב מכך, זמינות. האם רופא מסוים מקבל מטופלים חדשים? באילו ימים ושעות יש תורים פנויים? המידע הזה דינמי מאוד.
האתגר הטכני כאן הוא ניווט מורכב. זה לא רק לעבור על רשימה לינארית. ייתכן שתצטרך לבצע חיפוש לפי התמחות, לסנן לפי עיר, ולעבור על פני עמודי תוצאות מרובים (pagination). כל פעולה כזו היא אינטראקציה עם רכיבי UI שמפעילה קריאת API ברקע. עם Playwright, אפשר לחכות לרכיב ספציפי שיופיע, ללחוץ עליו, ואז ליירט את תגובת ה-API הרלוונטית. זה הרבה יותר יציב מאשר להשתמש ב-sleep() או להסתמך על סלקטורים של CSS בלבד. בקנה מידה של 5,000+ פרופילים, שמירה על קצב של 2-3 בקשות בשנייה עם headless browser אחד היא יעד ריאלי, בתנאי שאתה מנהל את הסשן נכון.
ה-Failure Scenario הקלאסי: ניהול סשן ו-Tokens
כאן רוב ה-scrapers נשברים. אתה בונה לוגיקה מושלמת, מריץ אותה על 10 דפים והכל עובד. אתה מריץ על 1000, ופתאום 95% מהבקשות נכשלות עם שגיאות 401/403 או חוזרות לדף הבית. מה קרה? הסשן שלך פג. אתרים כמו מאוחדת לא יתנו לך למשוך דאטה בלי סוף מסשן אנונימי יחיד. הם מצפים לראות התנהגות שדומה למשתמש אמיתי, שכוללת שמירה על עוגיות ורענון טוקנים.
הכשל הספציפי שראיתי קורה כך: ה-scraper מתחיל, מקבל עוגיות סשן ראשוניות. הוא עובד במשך 15-20 דקות ואז ה-token (למשל, JWT) שמוטמע בעוגיות או ב-localStorage פג תוקף. ה-scraper, שלא מודע לכך, ממשיך לשלוח בקשות עם הטוקן הישן. השרת מזהה את הטוקן הפגום ומתחיל לדחות את כל הבקשות. הפתרון הוא לא רק לשמור עוגיות, אלא לבנות לוגיקה שמזהה תגובת 'פג תוקף' (לרוב 401 Unauthorized), ובתגובה מנווטת מחדש לדף הבית או מבצעת פעולה אחרת שמרעננת את הסשן. זה הופך את ה-scraper מסט של הוראות לינאריות למכונת מצבים (state machine) שיודעת להתאושש. אם אתה לא מטפל בזה, אחוזי ההצלחה שלך יצנחו מתחת ל-10% בריצות ארוכות.
מודיעין מתחרים והפקת API פרטי
מעבר למידע הגלוי, הערך האמיתי מגיע מניתוח אגרגטיבי. מודיעין מתחרים מאוחדת לא עוסק רק בשירות ספציפי, אלא במגמות. למשל, ניתוח פיזור גיאוגרפי של רופאים מומחים יכול להצביע על אזורים עם עודף או חוסר היצע. מעקב אחרי שינויים ברשימת השירותים המוצעים יכול לאותת על כניסה לתחומים חדשים. כל הנתונים האלה, כשנאספים באופן עקבי, הופכים לנכס אסטרטגי.
המטרה הסופית של פרויקטים רבים כאלה היא יצירת API / קובץ נתונים פרטי. במקום שהצוות שלך יצטרך לגשת לאתר כל פעם, ה-scraper רץ ברקע (למשל, פעם ביום) ומייצא את כל המידע הרלוונטי לקובץ CSV או ישירות לבסיס נתונים. קובץ יומי כזה יכול להגיע בקלות ל-20-50MB של דאטה נקי ומובנה. משם, קל לחבר כלי BI כמו Tableau או PowerBI כדי להציג דשבורדים ולזהות תובנות. זה הופך דאטה לא מובנה וקשה לגישה ממקור חיצוני למשאב פנימי זמין ומוכן לניתוח. אם אתה לא חושב על שכבת האחסון והצריכה הזו, אתה עושה רק חצי מהעבודה.
מתי Scraping הוא פשוט לא הגישה הנכונה
למרות כל מה שאמרתי, יש מצבים שבהם בניית scraper מורכב היא בזבוז זמן ומאמץ. חשוב לזהות אותם. אם כל מה שאתה צריך זה פיסת מידע אחת שמתעדכנת פעם בחצי שנה, כמו רשימת המרפאות הראשית, פשוט תעשה את זה ידנית. המאמץ ההנדסי הנדרש לבנות ולתחזק scraper יציב לא מצדיק את עצמו עבור צרכים כאלה. התחזוקה היא לא אפסית; סלקטורים משתנים, מבנה ה-API מתעדכן, והגנות חדשות יכולות להופיע.
תרחיש נוסף הוא כשהמידע שאתה מחפש פשוט לא חשוף ציבורית. למשל, מידע שדורש הזדהות חזקה עם תעודת זהות וסיסמה. ניסיון לעשות scraping למידע אישי של משתמשים הוא לא רק קושי טכני אדיר, אלא גם נכנס לתחום אפור מבחינה אתית ומשפטית. המטרה שלנו היא לאסוף מידע שזמין לציבור, גם אם הוא מוגש בצורה דינמית. אם הדלת נעולה ודורשת מפתח אישי, אל תנסה לפרוץ אותה. תמיד תעריך את יחס המאמץ-תועלת. לפעמים, הדרך המהירה ביותר לקבל את הנתונים היא פשוט להכיר בכך ש-scraping אינו הפתרון המתאים לבעיה הספציפית הזו. זה סימן לבשלות הנדסית, לא לכישלון.
ארכיטקטורה שעובדת: Proxies, Retries ו-Headless
בנינו את הלוגיקה, טיפלנו בסשנים, מה עכשיו? להריץ את זה מהמחשב שלך יעבוד לבדיקות, אבל ייכשל בסקייל. כדי לבצע מעקב מלאי/זמינות מאוחדת באופן אמין, אתה צריך ארכיטקטורה חסינה. זה מתחיל ב-Proxy Rotation. אל תנסה לבנות מנגנון כזה מאפס, זה כאב ראש. השתמש בספק פרוקסי איכותי. לרוב האתרים הישראליים, פרוקסי מסוג Datacenter יכול להספיק, אבל לאתרים מתוחכמים יותר, איך לבחור פרוקסי residential יכול להיות ההבדל בין הצלחה לכישלון.
שנית, מנגנון Retries חכם. רשתות לא יציבות, שרתים עמוסים, ופרוקסים יכולים להיכשל. ה-scraper שלך חייב לדעת לטפל בשגיאות רשת או בסטטוס קודים כמו 502, 503, או 429. לוגיקה פשוטה של ניסיון חוזר עם exponential backoff היא חובה. קרא על טיפול בשגיאות 429 כדי להבין איך לעשות את זה נכון. לבסוף, הפעל את ה-headless browser שלך (Playwright) במצב 'stealth'. ישנם סקריפטים וספריות שמקשים על זיהוי האוטומציה שלך, על ידי הסתרת מאפיינים ש-WebDriver חושף. מדריך Playwright stealth הוא נקודת פתיחה מצוינת. השילוב של שלושת המרכיבים האלה – פרוקסים, retries, ו-stealth – הוא מה שהופך סקריפט שביר למערכת איסוף נתונים אמינה.
