למה Scraper מבוסס Requests ייכשל תוך 10 דקות
בואו נהיה ברורים: גישת ה-HTTP requests הקלאסית מתה עבור אתרים כמו am-pm.co.il. הניסיון לשלוח בקשת GET פשוטה לדף קטגוריה יחזיר לך שלד HTML עם אלמנט <div id="root"> ריק. כל המידע – שמות מוצרים, מחירים, מבצעים – מגיע דרך קריאות XHR/Fetch שמתרחשות ברקע אחרי טעינת הדף. אפשר, תיאורטית, לפתוח את ה-DevTools, לעקוב אחרי ה-Network tab ולנסות לחקות את קריאות ה-API האלה. ראיתי צוותים מנסים את זה. זה עובד. לשבוע. ואז משהו קטן משתנה: header, פרמטר בשם _t עם timestamp, או חתימת טוקן שנוצרת בצד הלקוח. פתאום כל ה-scraper שלך נשבר. התחזוקה הופכת לסיוט. אתה מבלה יותר זמן בדיבאג של API פנימי מאשר באיסוף נתונים. הגישה הזאת פשוט שבירה מדי עבור פרויקט רציני שדורש אמינות של 99.9%+. המסקנה היא חד משמעית: אם אתה רוצה לבנות משהו יציב לטווח ארוך, אתה חייב להשתמש בכלי שמריץ דפדפן אמיתי. תפסיקו לבזבז זמן על reverse engineering של API פנימי. זה קרב אבוד מראש.
Playwright ו-Headless Browsers: הדרך הנכונה לאיסוף קטלוג
אז מה כן עובד? אוטומציה של דפדפן. ולשנת 2026, אם אתה לא משתמש ב-Playwright לפרויקטים חדשים, אתה פשוט נשאר מאחור. הוא מהיר יותר, יציב יותר וה-API שלו נקי יותר מזה של Selenium. כשמדובר במשימת איסוף קטלוג AM:PM, המטרה היא לעבור על עשרות קטגוריות וכ-8,000-10,000 מוצרים ייחודיים. עם Playwright, התהליך נהיה פשוט להפליא: אתה מנווט לדף, ממתין לסלקטור ספציפי שמכיל את רשימת המוצרים (למשל, div[data-testid="product-list"]), ואז שולף את המידע מה-DOM המלא. אין צורך להתעסק עם טוקנים או headers. הדפדפן עושה את כל העבודה בשבילך. השילוב של Playwright עם מדריך Playwright stealth הוא קריטי כדי להיראות כמו משתמש אמיתי. הוא מטפל אוטומטית בפרטים קטנים כמו user-agent, מאפייני navigator, וטביעות אצבע אחרות שהגנות מתקדמות מחפשות. זה לא רק חוסך זמן פיתוח, זה משפר דרמטית את אחוזי ההצלחה ומפחית את כמות החסימות. כשאתה רץ על קטלוג שלם, כל אחוז בשיעור ההצלחה מתורגם ישירות לאיכות הדאטה שלך.
אתגר המיקוד הגאוגרפי: ניהול סניפים ומלאי
אחד האתגרים הייחודיים באתרים כמו AM:PM הוא שהמידע תלוי הקשר. המחיר או הזמינות של מוצר עשויים להשתנות בין סניף תל אביב לסניף רמת גן. האתר מנהל את המיקום הנבחר כנראה דרך עוגייה (cookie) או local storage. אם תתעלם מזה, תקבל נתונים לא מדויקים או, במקרה הגרוע, את נתוני ברירת המחדל שלא מייצגים אף סניף אמיתי. פרויקט מעקב מלאי/זמינות AM:PM חייב לטפל בזה בצורה מתוחכמת. הפתרון הוא לבנות לוגיקה שמנהלת קונטקסטים נפרדים של הדפדפן (Browser Contexts ב-Playwright) עבור כל סניף שאתה רוצה לנטר. כל קונטקסט יכיל עוגיות ומצב משלו. התהליך נראה כך: פתח קונטקסט חדש, נווט לאתר, בצע את הפעולה של בחירת סניף ספציפי, ורק אז תתחיל את ה-scraping. אם יש לך 50 סניפים לנטר, אתה תנהל 50 קונטקסטים במקביל. זה דורש יותר זיכרון, אבל זה מבטיח שהנתונים על מלאי לפי מוצר מדויקים ברמה הגאוגרפית. ניסיון לחסוך פה ולנסות להחליף עוגיות ידנית באותו קונטקסט הוא מתכון ל-race conditions ולנתונים מזוהמים.
מודיעין מתחרים וניטור מחירים: סקייל, פרוקסיז, וקצב בקשות
כשהמטרה היא ניטור מחירים AM:PM או מודיעין מתחרים AM:PM בזמן אמת, המשחק משתנה. אתה כבר לא מבצע ריצה אחת ביום לאיסוף קטלוג, אלא דוגם מאות או אלפי מוצרים קריטיים כל שעה. כאן, ניהול קצב הבקשות וה-IP rotation הופך למרכז המערכת. שליחת 200 בקשות בדקה מאותו IP היא הדרך המהירה ביותר להיחסם. המערכת צריכה להיות מתוכננת לעבוד עם מאגר גדול של פרוקסיז. residential proxies הם כמעט דרישת חובה כאן, כי טווח ה-IPs שלהם נראה תמים לחלוטין למערכות ההגנה. יש לבנות מנגנון rotation חכם שיודע להחליף IP לא רק אחרי מספר בקשות, אלא גם בתגובה לשגיאות. קיבלת שגיאת 429? ה-IP הזה נשרף. זרוק אותו מהמאגר ונסה מיד עם IP חדש. טיפול בשגיאות 429 הוא לא אופציה, הוא חלק מהליבה. Latency הוא גם פקטור. אם כל בקשה לוקחת 3-4 שניות (כולל רינדור), וצריך לדגום 5,000 מוצרים, ריצה אחת תיקח מעל 4 שעות. לכן, הפעלה מקבילית (concurrency) היא הכרח. הרצת 20-30 worker-ים של Playwright במקביל יכולה להוריד את זמן הריצה לש_יקות בודדות.
מתי הגישה הזו לא מתאימה: כשהמטרה היא API נקי
למרות כל מה שאמרתי, יש תרחיש אחד שבו גישת ה-Headless Browser היא overkill. אם המטרה הסופית שלך היא לא רק הנתונים, אלא יצירת API / קובץ נתונים AM:PM לשימוש פנימי מהיר ויעיל, לפעמים כדאי לחזור לשולחן השרטוט. נניח שאתה צריך רק לבדוק מחיר של מוצר בודד בתגובה לאירוע במערכת שלך, עם latency של פחות מ-500ms. להרים אינסטנס של Playwright, לנווט לדף ולחלץ נתון אחד זה איטי מדי ויקר מדי במשאבים. במקרה הספציפי הזה, אולי כן יש מקום להשקיע את המאמץ ולבצע reverse engineering ממוקד לקריאת ה-API הספציפית שמביאה את פרטי המוצר. זה עדיין שביר, אבל עבור use case כירורגי עם דרישות latency קשוחות, זה יכול להיות ה-trade-off הנכון. זה לא מתאים לאיסוף קטלוג מלא, אבל מושלם לבדיקות נקודתיות ומהירות. המפתח הוא להבין את המטרה. אם המטרה היא דאטה מקיף ואמין, לך על דפדפן. אם המטרה היא מהירות תגובה ל-query בודד, חקירת ה-API הפנימי עשויה להיות הפתרון הפחות גרוע, כל עוד אתה מבין את חובת התחזוקה שזה מטיל עליך.
בניית ה-Data Pipeline: מעבר ל-Scraping עצמו
הוצאת המידע מ-AM:PM היא רק חצי מהעבודה. מה קורה עם ה-JSON הגולמי שחילצת? הוא חסר ערך בלי pipeline שמנקה, מנרמל ומעשיר אותו. השלב הראשון הוא תיקוף סכמה. האם קיבלת את כל השדות? האם המחיר הוא מספר? האם שם המוצר לא ריק? כל סטייה צריכה להפעיל התראה. לאחר מכן, נירמול. מחירים יכולים להופיע בפורמטים שונים ('29.90', '29.9', '₪29.90') – צריך להביא אותם למבנה אחיד, למשל, integer של אגורות. השלב האחרון הוא האחסון. לדחוף הכל ל-CSV זה פתרון מהיר אבל לא סקיילבילי. בסיס נתונים כמו PostgreSQL או אפילו מסמכי ב-MongoDB מאפשר שאילתות מורכבות, כמו מעקב אחר שינויי מחיר לאורך זמן. בסופו של דבר, המטרה היא לא רק לאסוף דאטה, אלא להפוך אותו לנכס שמיש. אם אתה לא משקיע לפחות 30% מהמאמץ הכולל ב-pipeline שאחרי ה-scraper, אתה בונה מערכת שתיפול תחת העומס של עצמה תוך כמה חודשים. זה ההבדל בין פרויקט חובבני למערכת דאטה מקצועית.
