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

בואו נשים את זה על השולחן: requests לא יביא אתכם רחוק באתר של פרטנר. רוב התוכן החשוב – ממחירים של חבילות ועד למפרטים של מכשירים – נטען דינמית אחרי שה-HTML הראשוני מגיע לדפדפן. זה סימן קלאסי לאתר שנבנה כ-Single Page Application (SPA), כנראה עם React או Angular. כשאתם שולחים בקשת HTTP פשוטה, אתם מקבלים שלד HTML כמעט ריק, בלי המידע שאתם באמת צריכים.

הפתרון היחיד שעובד בעקביות הוא להשתמש ב-headless browser. כן, זה דורש יותר משאבים, אבל זה ההבדל בין פרויקט שעובד לבין פרויקט שנתקע אחרי שבוע. תפסיקו עם Selenium לפרויקטים חדשים. Playwright מנצח אותו ב-2025 בכל מטריקה רלוונטית – מהירות, יציבות, וה-API שלו פשוט נקי יותר. היכולת שלו ליירט בקשות רשת היא קריטית כאן. במקום לעשות parse ל-DOM המלא והמסורבל, אפשר פשוט להקשיב לבקשות ה-API הפנימיות שהדפדפן שולח, ולחלץ את ה-JSON הנקי ישירות משם. זה מקטין את התלות בסלקטורים של CSS שבירים, ומאיץ את תהליך ה-scraping ב-30-40% לפחות, כי לא צריך לחכות לרינדור מלא של כל פיקסל על המסך.

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

כשמטרגטים אתר כמו פרטנר, המטרה היא לא רק להוציא דף אחד. המטרה היא לבנות מערכת אמינה לשימושים כמו איסוף קטלוג פרטנר מלא או ניטור מחירים פרטנר מתמשך. הקטלוג שלהם מכיל מאות, אם לא אלפי, וריאציות של מוצרים, חבילות ומבצעים. ארכיטקטורה נכונה מפרידה בין גילוי (discovery) לבין חילוץ (extraction).

שלב הגילוי צריך להיות קל ומהיר. Crawler ייעודי סורק את מפת האתר, את דפי הקטגוריות והתפריטים כדי לייצר רשימה של כל כתובות ה-URL של המוצרים והחבילות. התוצר של השלב הזה הוא תור (queue) של משימות, למשל ב-Redis או RabbitMQ. אל תנסו לעשות גילוי וחילוץ באותו תהליך. זה מתכון לאסון.

השלב השני הוא החילוץ. פה נכנסים ה-workers הכבדים, שמריצים Playwright. כל worker לוקח משימה מהתור, מנווט ל-URL, ומחלץ את השדות הנדרשים: מחירים, מבצעים, שמות מוצרים, מפרטים טכניים וכו'. אם אתם לא משתמשים ב-async ל-1000+ דפים, אתם מבזבזים 80% מהזמן על המתנה ל-IO. דרישת חובה, לא nice-to-have. עם ארכיטקטורה כזו, אפשר להגיע לקצבים של 500-1000 דפים בשעה עם מספר מצומצם של workers, תוך שמירה על אחוזי הצלחה של מעל 98%.

המלכודת: זמינות מבוססת מיקום וסשנים

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

האתר עשוי להשתמש ב-cookies או ב-session storage כדי לזכור את הכתובת שהוזנה בבדיקת הזמינות. אם לא מנהלים את הסשנים נכון, כל בקשה שלכם תיראה כמשתמש חדש, ותקבלו נתונים לא עקביים. כדי לטפל בזה, צריך לדמות את תהליך בדיקת הזמינות: לנווט לעמוד הרלוונטי, להזין כתובת (מתוך מאגר כתובות מייצגות), ולשמור את ה-context של הדפדפן (cookies ו-storage) עבור כל הבקשות העתידיות שקשורות לאותו אזור. זה דורש שימוש ב-proxy pool מגוון, ורצוי להבין איך לבחור פרוקסי residential כדי לדמות משתמשים אמיתיים מאזורים שונים בישראל. בלי זה, אתם פשוט אוספים מידע חלקי ולא שמיש.

מודיעין מתחרים והפקת API פרטי מהאתר

מעבר לאיסוף נתונים גולמי, הערך האמיתי מגיע מהפיכת המידע הזה למוצר שמיש. שני מקרי שימוש מרכזיים הם מודיעין מתחרים פרטנר ויצירת API / קובץ נתונים פרטנר פרטי לשימוש פנימי. עבור מודיעין מתחרים, לא מספיק לאסוף את המחיר. צריך לתעד את היסטוריית השינויים, לזהות השקה של מבצעים חדשים, ולהצליב את המידע עם נתונים מספקים אחרים. זה דורש בסיס נתונים מובנה היטב, עם חותמות זמן לכל שינוי.

השלב הבא הוא הנגשת המידע. במקום לתת למשתמשי הקצה גישה ל-CSV ענק, בונים API פנימי פשוט (למשל עם FastAPI) שחושף את הדאטה. Endpoint כמו /products/{sku} או /competitor/partner/promotions הופך את המידע לזמין וקל לצריכה עבור צוותי אנליסטים או מערכות אוטומטיות. תהליך כזה, מקצה לקצה, לוקח זמן לבנות, אבל הוא משלם על עצמו מהר מאוד במורכבות שהוא חוסך משאר הארגון. חשוב לזכור שה-scraper הוא רק החלק הראשון בשרשרת. ניקוי הנתונים, נרמול, ואחסון הם 80% מהעבודה האמיתית.

מתי Scraping הוא לא הפתרון הנכון (כן, יש מקרים כאלה)

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

תרחיש נוסף הוא כשהאתר מוגן על ידי מערכות anti-bot אגרסיביות במיוחד כמו Cloudflare בגרסה הארגונית שלו או Imperva. במקרים כאלה, המאמץ הנדרש כדי לעקוף את ההגנות יכול להיות אדיר. זה הופך למשחק חתול ועכבר שדורש תחזוקה מתמדת, וצריך להכיר טכניקות מתקדמות כמו שמוסבר במדריך לעקיפת Cloudflare. אם אין לכם את המשאבים או המומחיות להתמודד עם זה לאורך זמן, ייתכן שהפרויקט נידון לכישלון. לפעמים, הדרך החכמה היא להכיר במגבלות ולהבין מתי המאמץ פשוט לא מצדיק את התוצאה הצפויה. תמיד תשאלו את עצמכם: האם יש דרך פשוטה יותר להשיג את המידע שאני צריך?