למה בכלל לעשות סקרייפינג לקק"ל? מעבר למודיעין תחרותי
בדרך כלל אנחנו מדברים על scraping בהקשרים של מודיעין מתחרים או ניטור מחירים. אבל אתר כמו קק״ל פותח עולם שלם של שימושים אחרים. תחשבו על בניית API / קובץ נתונים קק״ל שלא קיים רשמית, ומספק מידע בזמן אמת על מצב שבילים, פריחות עונתיות או עומס באתרים. זה יכול להיות בסיס לאפליקציית טיולים, למחקר אקדמי על שינויים סביבתיים, או פשוט כפרויקט דאטה אישי.
אחד ה-use cases המעניינים הוא איסוף קטלוג של כלל נכסי הארגון: יערות, חניונים, אתרים ארכיאולוגיים, ופרויקטים קהילתיים. מדובר על אלפי נקודות עניין. איסוף שיטתי של שמות המוצרים/מודעות (במקרה הזה, שמות האתרים והפרויקטים) וסיווגם לפי קטגוריות (אזורים גיאוגרפיים, סוגי פעילות) מאפשר ליצור מאגר מידע שאין לו אח ורע. דמיינו שאתם יכולים להריץ שאילתה כמו "הצג לי את כל חניוני הלילה עם נגישות לנכים באזור הצפון שהתווספו בחצי השנה האחרונה".
גם מושגים כמו מעקב מלאי/זמינות קק״ל מקבלים פה משמעות חדשה. במקום מלאי של מוצרים, אנחנו עוקבים אחרי מקומות פנויים בסיורים מודרכים, זמינות של תאריכים לאירועים, או אפילו "מלאי" של שתילים בפרויקטי נטיעות. המידע הזה קיים באתר, אבל הוא מפוזר ולא נגיש. סקרייפר טוב יכול לרכז אותו ולהפוך אותו לבר-שימוש.
המלכודת הראשונה: המפות האינטראקטיביות
רוב המידע המעניין באתר קק״ל לא יושב בטבלאות HTML פשוטות. הוא מוטמע בתוך מפות אינטראקטיביות, ככל הנראה מבוססות על טכנולוגיית GIS כמו Esri ArcGIS. אם תנסו לגשת עם סקרייפר פשוט מבוסס requests ו-BeautifulSoup, תקבלו דף ריק או div בודד שמכיל את אפליקציית המפה. כל המידע נטען דינמית דרך קריאות API פנימיות שהדפדפן מבצע.
כאן רוב המפתחים המתחילים נתקעים. הם מנסים לחקות את הקריאות האלה ידנית, אבל נתקלים בבעיות של טוקנים, headers מורכבים ו-CORS. הדרך הנכונה היא לא להילחם ב-API, אלא להשתמש בו. פתחו את ה-DevTools ברשת (Network tab), סננו לפי XHR/Fetch, וצפו בתעבורה בזמן שאתם מבצעים אינטראקציה עם המפה. תגלו קריאות ל-endpoints שמחזירים GeoJSON או מבני JSON אחרים עם קואורדינטות, שמות אתרים, תיאורים וקישורים. זה זהב טהור.
הגישה המנצחת כאן היא Headless Browser. תפסיקו עם Selenium, הוא איטי ומיושן. Playwright הוא הבחירה הנכונה ב-2025. הוא מאפשר לכם ליירט את בקשות הרשת האלה בקלות. אתם יכולים לטעון את הדף, להמתין שהמפה תיטען, ואז פשוט לאסוף את התשובות של קריאות ה-API הרלוונטיות. זה הרבה יותר יציב מלחפש סלקטורים ב-DOM שמשתנים כל הזמן. קראו עוד על הגישה הזו ב-מדריך Playwright stealth, כי גם אתרים ציבוריים מתחילים להפעיל הגנות בסיסיות.
תכנון הסקרייפר: קצב, פרוקסי וניהול סשנים
בניגוד לאתרי מסחר אלקטרוני אגרסיביים, סביר להניח שקק״ל לא מפעילים מערכות Anti-bot מהשורה הראשונה כמו Cloudflare או Akamai. זה לא אומר שאפשר להפציץ אותם באלפי בקשות בדקה. סקרייפינג אחראי הוא המפתח כאן. התחילו עם קצב נמוך ומכבד, נניח בקשה כל 2-3 שניות (20-30 RPM). זה מספיק מהר כדי לאסוף את כל בסיס הנתונים שלהם, המוערך בכ-10,000-15,000 ישויות (אתרים, מסלולים, אירועים), תוך מספר שעות, מבלי להעמיס על השרתים שלהם.
גם אם אין הגנה אקטיבית, הרצה של סקרייפר מ-IP של דאטה סנטר (AWS, GCP) היא דרך בטוחה להיחסם בסופו של דבר. ה-IP שלכם יופיע ב-blacklists ציבוריים. לכן, שימוש בפרוקסי הוא עדיין חובה. לא תצטרכו את התותחים הכבדים, אבל רשת של איך לבחור פרוקסי residential ישראליים תבטיח שהתעבורה שלכם תיראה אורגנית לחלוטין. רוטציה פשוטה בין 10-20 פרוקסיז תספיק.
נקודה נוספת היא ניהול סשנים. חלק מהאזורים באתר, במיוחד אלה שקשורים להרשמה לאירועים או פעילויות, עשויים לדרוש עוגיות (cookies) או טוקנים של CSRF. ספריות כמו requests.Session מטפלות בזה אוטומטית, אבל אם אתם משתמשים ב-Playwright, הדפדפן מנהל את זה בשבילכם. המלכודת היא בניסיון לשלב בין השניים – למשל, לחלץ טוקן עם Playwright ולהשתמש בו ב-requests. אל תעשו את זה. תבחרו גישה אחת ותישארו איתה לכל אורך התהליך. זה יחסוך לכם שעות של דיבאגינג.
מתי הגישה הזו לא תעבוד: תוכן בתוך קבצים
כל מה שדיברנו עליו עובד מצוין עבור מידע מובנה שמוצג ב-HTML או נטען דרך API כ-JSON. אבל יש סוג של תוכן שבו הגישה הזו נכשלת: מידע שקבור בתוך קבצי PDF, Word או Excel. באתרים ממשלתיים וציבוריים כמו קק״ל, זהו תרחיש נפוץ. דוחות שנתיים, פרוטוקולים, מכרזים, מפות טופוגרפיות סרוקות – כל אלה הם אוצרות של מידע, אבל הם לא נגישים לסקרייפר רגיל.
אם מטרת ה-scraping שלכם היא לחלץ נתונים מטבלה שנעולה בתוך PDF בן 200 עמודים, Playwright לא יעזור לכם. במקרה הזה, העבודה מתחלקת לשניים: השלב הראשון הוא סקרייפינג קלאסי לאיתור וזיהוי כל הקישורים לקבצים הרלוונטיים והורדתם למערכת הקבצים המקומית. זה החלק הקל. החלק השני, והמורכב הרבה יותר, הוא עיבוד הקבצים עצמם. תצטרכו להשתמש בספריות ייעודיות כמו PyPDF2 או pdfplumber לפייתון, או כלים מבוססי OCR (זיהוי תווים אופטי) כמו Tesseract אם מדובר בקבצים סרוקים. זה פרויקט בפני עצמו, עם אחוזי הצלחה נמוכים יותר וצורך בהרבה יותר לוגיקה מותאמת אישית לכל סוג של מסמך. אם 80% מהמידע שאתם צריכים נמצא בקבצים כאלה, תכננו את המאמץ שלכם בהתאם. זה כבר לא פרויקט של סוף שבוע.
בניית הדאטהסט הסופי: ניקוי, סטנדרטיזציה וייצוא
איסוף הנתונים הוא רק חצי מהעבודה. השלב הבא, והחשוב לא פחות, הוא להפוך את הג'יבריש שאספתם לדאטהסט נקי ושימושי. הנתונים מאתר קק״ל, כמו מכל אתר גדול, יהיו מבולגנים. תקבלו שמות של אתרים עם שגיאות כתיב, קואורדינטות בפורמטים שונים, תיאורים שמכילים תגיות HTML, ותאריכים במבנים לא אחידים ('12/05/2024', 'מחר', 'יום העצמאות').
השלב הראשון הוא נורמליזציה. החליטו על פורמט אחיד לכל שדה. תאריכים צריכים להיות בפורמט ISO 8601. קואורדינטות צריכות להיות בפורמט עשרוני סטנדרטי. טקסט חופשי צריך לעבור ניקוי מתגיות HTML, רווחים כפולים ותווים מיוחדים. השתמשו בספריות כמו pandas בפייתון כדי לטעון את כל המידע ל-DataFrame ולבצע את הטרנספורמציות האלה בצורה וקטורית ויעילה.
השלב השני הוא העשרה (Enrichment). לדוגמה, אם חילצתם רק שם של יישוב, תוכלו להשתמש ב-API חיצוני (כמו geocoding) כדי להוסיף קואורדינטות, או להפך. תוכלו גם ליצור שדות חדשים ממידע קיים, כמו חישוב מרחקים בין נקודות עניין.
בסוף התהליך, המטרה היא לקבל ייצוא CSV/API יומי או שבועי שכל שורה בו מייצגת ישות אחת (אתר, מסלול) וכל עמודה היא תכונה ברורה ונקייה. דאטהסט כזה, המתעדכן אוטומטית, הוא הנכס האמיתי. אם תתקלו ב-rate limiting בשלב האיסוף, זכרו ליישם לוגיקת retry עם exponential backoff. זה נושא קריטי שרבים מזלזלים בו, ותמצאו מידע נוסף בפוסט על טיפול בשגיאות 429.
