למה requests פשוט לא יעבוד כאן
בואו נשים את זה על השולחן: אם אתם מתחילים פרויקט על אתר כמו משלוחה עם requests, אתם בונים על יסודות רעועים. שליחת בקשת GET פשוטה ל-URL של מסעדה תחזיר לכם מעטפת HTML ריקה, עם תג <div id="root"> ותגי <script> שיטענו את האפליקציה. כל המידע שאתם צריכים — תפריטים, מחירים, מבצעים, זמינות — נטען דינמית דרך קריאות API (XHR/Fetch) לאחר שה-JavaScript רץ בדפדפן. לנסות לנתח את ה-HTML הראשוני זה בזבוז זמן.
הפתרון הוא לא לנסות להנדס לאחור את ה-API הפנימי שלהם. זה אולי יעבוד לשבוע, אבל בשינוי ה-endpoint הבא, כל המערכת שלכם תקרוס. הגישה היציבה יותר היא להשתמש ב-headless browser שמריץ את ה-JS בדיוק כמו משתמש אמיתי. תפסיקו עם Selenium לפרויקטים חדשים. Playwright מנצח אותו ב-2025 בכל מטריקה רלוונטית, ממהירות ועד יציבות. עם Playwright, אתם יכולים לחכות לאלמנטים ספציפיים שיופיעו על המסך, מה שמבטיח שהנתונים כבר שם לפני שאתם מנסים לחלץ אותם. זה חיוני במיוחד עבור משימה כמו איסוף קטלוג משלוחה, שדורשת מעבר בין עשרות קטגוריות ומסעדות שכולן נטענות אסינכרונית. אם אתם לא מכירים את הכלים המודרניים, כדאי שתקראו את המדריך המלא ל-Playwright עם stealth כדי להבין את היכולות.
משחק המיקומים: הבעיה האמיתית של משלוחה
האתגר הגדול ביותר ב-scraping של משלוחה הוא לא טכני במובן של עקיפת הגנות, אלא לוגי. כל התוכן באתר — רשימת המסעדות, שעות הפעילות, המבצעים, ואפילו עצם הזמינות של מסעדה מסוימת — משתנה דרמטית בהתבסס על כתובת המשלוח. זה אומר שאי אפשר פשוט לגרד את האתר. צריך לגרד אותו מתוך הקשר של מיקום ספציפי.
כאן רוב המהנדסים עושים טעות קריטית. הם מריצים את ה-scraper שלהם מ-IP של דאטה סנטר באירלנד ומקבלים תוצאות לא רלוונטיות, או גרוע מכך, הודעת שגיאה. אתם חייבים לדמות משתמש שנמצא בכתובת פיזית בישראל. הדרך לעשות את זה נכון היא להשתמש ב-proxies, אבל לא סתם. אתם צריכים פרוקסי residential ישראלי שיאפשר לכם להגדיר מיקום ברמת העיר. לאחר מכן, באמצעות Playwright, עליכם להזין כתובת ספציפית בשדה החיפוש ולחכות שהעמוד יתעדכן. כל בקשה לאיסוף נתונים חייבת להתבצע בתוך ה-session הזה, עם ה-cookie ששומר את המיקום.
תרחיש כשל קלאסי שראיתי קורה שוב ושוב: scraper רץ על רשימת כתובות בתל אביב, ואז באמצע הריצה, אחד ה-proxies מתחלף לאחד שמזוהה בחיפה. ה-scraper לא מזהה את שינוי ההקשר, ממשיך לאסוף נתונים, ומכניס לדאטהבייס תפריטים ומחירים של מסעדות חיפאיות תחת כתובות תל אביביות. הנתונים מושחתים וחסרי ערך.
קצב, טביעות אצבע, ואיך לא להיחסם
משלוחה, כמו כל פלטפורמה מודרנית, לא אוהבת תנועה רובוטית. עם זאת, ההגנות שלהם מתוחכמות יותר מכמה כללי robots.txt. הם משתמשים במנגנונים לזיהוי טביעות אצבע של הדפדפן (fingerprinting) ובניתוח התנהגותי. אם תנסו לפתוח 500 עמודי מסעדות במקביל מאותו IP, סביר להניח שתקבלו CAPTCHA או חסימה זמנית. הגישה הנכונה היא לחקות התנהגות אנושית, אבל בקנה מידה.
קודם כל, קצב. אל תפציצו את השרתים. קצב סביר של 20-30 בקשות לדקה פר IP הוא נקודת פתיחה טובה. אם אתם צריכים קצב גבוה יותר, אל תגבירו את המהירות פר IP, אלא הוסיפו עוד IPs למאגר שלכם. שנית, טביעת אצבע. השתמשו בתוספי stealth ל-Playwright. הם דואגים להסתיר את העובדה שהדפדפן נשלט על ידי אוטומציה (למשל, על ידי הסרת המשתנה navigator.webdriver).
בנוסף, גוונו את מסלולי הגלישה. אל תלכו תמיד ישירות ל-URL של המסעדה. דמו תהליך חיפוש: נחיתה בעמוד הראשי -> הזנת כתובת -> בחירת קטגוריה -> לחיצה על מסעדה. התהליך הזה, למרות שהוא מוסיף latency של 2-3 שניות לכל session, מייצר תנועה שנראית אורגנית יותר ומוריד את סיכויי החסימה באופן משמעותי. כישלון בניהול טביעות אצבע יוביל אתכם למצב מתסכל של טיפול בשגיאות 429 ו-CAPTCHAs במקום לאסוף נתונים. אם אתם נתקלים ב-Cloudflare, יש טכניקות ספציפיות שצריך להכיר, אבל זה כבר נושא לדיון נפרד.
האתגר השקט: איסוף וניהול מבצעים משתנים
אחד ה-use cases המורכבים ביותר הוא ניטור מחירים משלוחה, ובפרט, מעקב אחר מבצעים. מבצעים באתר כמו משלוחה הם דינמיים מאוד. הם יכולים להיות תלויי שעה, תלויי מיקום, ספציפיים למשתמשים חדשים, או קשורים להזמנה מעל סכום מסוים. לחלץ את הטקסט "1+1 על כל הפיצות" זה החלק הקל. האתגר הוא להבין את ההקשר והתנאים של המבצע.
כדי לעשות זאת נכון, ה-scraper שלכם צריך להיות יותר מורכב מסתם כלי לחילוץ טקסט. הוא צריך להיות מסוגל לפרסר את הלוגיקה של המבצע. זה אומר לחפש אלמנטים נסתרים, tooltips, או אפילו קטעי JSON מוטמעים ב-HTML שמכילים את תנאי המבצע. לעיתים קרובות, המידע הזה לא מוצג ישירות למשתמש אלא מופיע רק לאחר אינטראקציה, כמו הוספת פריט לסל.
בפרויקט שעבדתי עליו, גילינו שחלק מהמבצעים הופיעו רק לאחר שהסל עבר סף מסוים. היינו צריכים לבנות לוגיקה שהוסיפה פריטים לסל באופן אוטומטי כדי לחשוף את המבצעים הנסתרים הללו. זה הוסיף כ-50% למורכבות הלוגית של ה-scraper, אבל איכות הנתונים שהתקבלה הייתה גבוהה לאין שיעור. בסופו של דבר, הנתונים האלה משמשים לטובת מודיעין מתחרים משלוחה, והבנת מבנה המבצעים היא קריטית.
מתי לא כדאי לבנות Scraper למשלוחה בעצמכם
אחרי כל מה שאמרתי, חשוב להיות ריאליים. לא תמיד בניית scraper מאפס היא ההחלטה הנכונה. ישנם תרחישים שבהם המאמץ פשוט לא מצדיק את התוצאה, במיוחד אם הצורך שלכם הוא חד-פעמי או בקנה מידה קטן. אם כל מה שאתם צריכים זה רשימה של 50 מסעדות באזור מסוים פעם בחודש, כנראה שעדיף לעשות את זה ידנית. הזמן שתשקיעו בהקמת סביבה, ניהול proxies, וטיפול בחסימות יעלה על התועלת.
נקודה נוספת היא תחזוקה. אתרים כמו משלוחה משנים את המבנה שלהם לעיתים קרובות. שינוי קטן ב-class name או במבנה ה-DOM יכול לשבור לכם את ה-scraper. אם אין לכם צוות שמסוגל להקדיש 2-3 שעות שבועיות לתחזוקה וניטור, המערכת שלכם תהפוך מהר מאוד ללא אמינה. פרויקט API / קובץ נתונים משלוחה דורש אמינות של 99.9% לפחות. אם אתם לא יכולים להתחייב לרמת התחזוקה הזו, ייתכן שפתרון מנוהל או רכישת דאטה סט מוכן יתאימו יותר ויחסכו לכם כאבי ראש משמעותיים בטווח הארוך. בניית scraper זה לא פרויקט של 'שגר ושכח'. זו התחייבות מתמשכת.
