למה סקריפט ה-requests הפשוט שלך ייחסם תוך 20 דקות

בואו נשים את זה על השולחן. אם הגישה הראשונית שלכם ל-Rest היא לולאה פשוטה עם ספריית requests, אתם בדרך הבטוחה לחסימה. מהר מאוד. המערכות של Rest לא נאיביות; הן מזהות בקלות תעבורה שנראית רובוטית. אחרי כ-500 בקשות רציפות מאותו IP, אתם תתחילו לראות שגיאות 403, לא 429. זו לא בקשה למתן את הקצב, זו דלת שנטרקת לך בפנים.

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

ה-failure scenario הקלאסי באתר מסעדות כמו Rest הוא לא רק חסימת IP. זה משהו מתוחכם יותר: קבלת נתונים חלקיים או שגויים. המערכת עשויה להחזיר לכם עמוד קטגוריה שנראה תקין, אבל חלק מהמנות פשוט לא מופיעות בו. בלי מנגנון אימות קפדני, אתם תאספו קטלוג חסר ותחשבו שהכל בסדר. זה הרגע שבו אתם מבינים ש-scraping מודרני דורש יותר מסתם שליפת HTML.

ארכיטקטורה שעובדת: Playwright, רוטציית פרוקסי, ו-State Management

אז מה כן עובד? גישה מבוססת דפדפן אמיתי. ותפסיקו להשתמש ב-Selenium לפרויקטים חדשים. Playwright מנצח אותו ב-2025 בכל מטריקה רלוונטית, במיוחד בביצועים וב-API האסינכרוני שלו. עבור Rest, שימוש ב-Playwright עם תוסף stealth הוא קו הבסיס, לא בונוס. זה מאפשר לנו לעקוף את רוב בדיקות ה-fingerprinting הבסיסיות שהאתר מפעיל.

השלב הבא הוא רוטציית פרוקסי חכמה. לא מספיק להחליף IP כל בקשה. צריך לנהל סשנים. כשמשתמש אמיתי גולש, הוא נשאר עם אותו IP לאורך זמן. המערכת שלנו צריכה לחקות את זה. אנחנו משתמשים ב-sticky sessions, כאשר כל worker בתור שלנו מקבל פרוקסי ייעודי למשך סשן של 10-15 דקות, מספיק זמן כדי לנווט בכמה קטגוריות ולהיראות אנושי. המדריך שלנו על איך לבחור פרוקסי residential יכול לתת לכם כיוון טוב לגבי סוגי הפרוקסי המתאימים למשימה כזו.

לבסוף, ניהול מצב (state management) הוא קריטי. אי אפשר פשוט להריץ את כל ה-scraper מהתחלה בכל פעם. אנחנו שומרים במטמון (למשל ב-Redis) את רשימת הקטגוריות וקישורי המוצרים שכבר סרקנו, יחד עם timestamp. כך, בריצה הבאה, אנחנו יכולים להתמקד רק במה שהשתנה או במה שנכשל. זה מקטין את כמות הבקשות בכ-80% בריצות תחזוקה ומצמצם דרמטית את הסיכוי לחסימה.

איסוף קטלוג מלא: מעבר לדפים הראשיים

אחד השימושים המרכזיים הוא איסוף קטלוג Rest המלא. זה נשמע פשוט, אבל השטן נמצא בפרטים. הניווט באתר הוא לא לינארי. יש קטגוריות, תת-קטגוריות, פילטרים, ודפים שמתגלים רק אחרי אינטראקציה ספציפית. הגישה הנכונה היא לבנות "עכביש" (spider) רקורסיבי.

התהליך מתחיל מדף הבית. הסורק מזהה את כל הקישורים לקטגוריות הראשיות ומכניס אותם לתור (queue). כל worker שלוקח משימה מהתור מנווט לקטגוריה, אוסף את כל המוצרים בעמוד הנוכחי, ומחפש קישורי עמודים נוספים (pagination). במקביל, הוא מחפש קישורים לתת-קטגוריות או פילטרים ומכניס גם אותם לתור. המפתח הוא לזהות תבניות URL ייחודיות כדי למנוע לולאות אינסופיות. קטלוג המסעדות המלא של Rest כולל למעלה מ-150,000 פריטים ייחודיים הפרוסים על פני אלפי דפים. סריקה מלאה שלו יכולה לקחת כמה שעות טובות, אפילו עם תשתית מקבילית.

במהלך הסריקה, אנחנו לא רק אוספים שמות. אנחנו מחלצים את כל ה-מפרטים של כל מנה: תיאור, רכיבים, אפשרויות התאמה אישית, ותמונות. הנתונים האלה נשמרים בפורמט JSON מובנה, מוכנים לעיבוד. פרויקט כזה יכול לייצר בקלות 5-10GB של נתונים גולמיים בסריקה ראשונית אחת.

ניטור שינויים בזמן אמת ומודיעין מתחרים

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

במקום לסרוק את כל האתר שוב ושוב, אנחנו מפעילים סורקים ממוקדים. יש לנו רשימת "פריטים חמים" (high-priority items) שנסרקת כל 15 דקות. שאר הקטלוג נסרק בתדירות נמוכה יותר, אולי פעם ב-4-6 שעות. המטרה היא לא להעמיס על השרתים של Rest, אלא לבצע שאילתות כירורגיות. עם ארכיטקטורה אסינכרונית טובה, אפשר להגיע לקצב של 200-300 דפים בדקה עם latency ממוצע של 2.5 שניות לדף (כולל רינדור JS), תוך שמירה על אחוז הצלחה של 99.5%.

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

מתי הגישה הזו היא Overkill (ולמה זה נדיר)

אני תמיד טוען שצריך להתאים את הכלי למשימה. אז מתי הארכיטקטורה המורכבת הזו, עם Playwright וניהול פרוקסי, היא פשוט יותר מדי? אם כל מה שאתם צריכים זה רשימה של שמות המסעדות הפופולריות ביותר פעם בחודש, אז כן, זה overkill. סקריפט פשוט כנראה יעשה את העבודה, ואם ייחסם, אפשר להריץ אותו ידנית מ-IP אחר.

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

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