למה ה-Scraper הסטנדרטי שלך ייכשל על yes
הטעות הראשונה שרוב המהנדסים עושים היא להתייחס ל-yes.co.il כאל אתר רגיל. הם מריצים requests או curl, מקבלים HTML ריק מתוכן, ומתחילים להסתבך. הסיבה פשוטה: האתר הוא Single Page Application (SPA). התוכן שאתה רואה – רשימת הערוצים, קטלוג ה-VOD, מבצעים – לא קיים במקור הדף. הוא נטען דינמית באמצעות JavaScript שמבצע קריאות לרשת של שירותי API פנימיים.
זה אומר שכל ניסיון לגשת למידע עם ספריות HTTP פשוטות נידון לכישלון. אתה צריך לעבור לכלים שמריצים דפדפן מלא, כמו Playwright או Puppeteer. ואני אגיד את זה חד וחלק: אם אתם מתחילים פרויקט חדש ב-2025, תעזבו את Selenium. Playwright מהיר יותר, הא-סינכרוניות שלו מובנית בצורה טובה יותר, וה-API שלו פשוט נקי יותר. כשאתה צריך לטפל במאות אלפי פריטי תוכן, ההבדל בביצועים בין שליחת בקשת HTTP (שנכשלת) לבין רינדור דף מלא הוא עצום. Latency של 250ms לעומת 2-3 שניות לדף. אבל זו רק ההתחלה. הבעיה האמיתית היא לא רק רינדור הדף, אלא הבנת רשת הקריאות הפנימיות שהוא מבצע כדי למצוא את מקור הנתונים האמיתי. שם נמצא הזהב.
פענוח ה-API הפנימי: הגישה שעובדת באמת
אז הבנו שצריך דפדפן. השלב הבא הוא לא להתחיל לגרד את ה-DOM. זה שביר, איטי ודרך בטוחה לתחזוקה אינסופית. במקום זה, פתחו את ה-Developer Tools (F12) ולכו לטאב Network. רעננו את אחד מעמודי הקטלוג ותראו את מטר הקריאות. רובן יהיו תמונות וסקריפטים, אבל ביניהן תמצאו קריאות fetch/XHR שמחזירות JSON נקי ומסודר. זה היעד שלכם.
בפרויקט איסוף קטלוג yes, זיהינו endpoint מרכזי שמחזיר את מבנה הקטגוריות, ועוד כמה endpoints שמאכלסים כל קטגוריה בנפרד, עם pagination. המטרה היא לדמות את הקריאות האלה ישירות, ולעקוף את הדפדפן לחלוטין ב-95% מהזמן. איך עושים את זה? מבודדים את הקריאה, מעתיקים אותה כ-cURL, ומנתחים את ה-headers, ה-cookies, וה-payload. לעיתים קרובות תמצאו token שצריך לחלץ מקריאה ראשונית או מה-HTML. ברגע שיש לכם את המתכון לקריאת API אחת, אתם יכולים להריץ אלפי קריאות כאלה במקביל, עם latency ממוצע של 150ms במקום שניות, ולהגיע לקצבי סריקה גבוהים בהרבה. זה המעבר מאיסוף נתונים ארכאי לגישה מודרנית שמייצרת API / קובץ נתונים מסודר ויעיל. חשוב לזכור שגם קריאות API דורשות ניהול חכם של פרוטוקול ה-HTTP ו-headers כדי להיראות כמו תנועה לגיטימית.
תרחיש כשל קלאסי: שינוי מבנה התגובה של ה-API
בנינו הכל סביב ה-API הפנימי. ה-scraper רץ חלק, 99.8% הצלחה, אוסף נתונים כמו שעון במשך חודשיים. ואז, בוקר אחד, הכל מתחיל ליפול. כל הבקשות מחזירות 200 OK, אבל הדאטהבייס מתחיל להתמלא בערכי null. זה תרחיש כשל קלאסי באתרי מדיה כמו yes, והוא כמעט תמיד נובע משינוי שקט ב-API.
זה לא שה-endpoint נעלם, אלא שמבנה ה-JSON שהוחזר השתנה. שדה שקראו לו programTitle הפך ל-title, או שמבנה הקינון של מפרטים טכניים השתנה. ה-scraper שלך, שמצפה למבנה ספציפי, לא מוצא את הנתיב ומחזיר null. מכיוון שקוד התגובה הוא 200, מערכות ניטור בסיסיות לא יתריעו. הנזק מתגלה רק שעות או ימים אחר כך, כשהאנליסטים רואים חורים בנתונים. הפתרון הוא לא רק לנטר קודי HTTP, אלא לבצע ולידציה על סכמת הנתונים עצמה. כלים כמו Pydantic (בפייתון) או Zod (ב-Node.js) הם חובה. אחרי כל תגובת API מוצלחת, תריצו ולידציה על המבנה. אם היא נכשלת, ה-scraper צריך לעצור ולשלוח התראה מפורטת. זה ההבדל בין פרויקט חובבני למערכת production-grade שיודעת לזהות תקלות תוך דקות.
איך בונים מערך ניטור מחירים ומבצעים בקנה מידה גדול
אחד ה-use cases המרכזיים הוא ניטור מחירים yes – מעקב אחר שינויים בחבילות, מבצעים חדשים, או שינויים בתמחור של תכני VOD. זה דורש יותר מסריקה חד-פעמית; זה דורש תהליך מתמשך, מתוזמן ואמין. האתגר הוא לא רק טכני אלא גם לוגי. קטלוג התוכן של yes כולל עשרות אלפי פריטים. סריקה מלאה של הכל בכל שעה היא בזבוז משאבים. צריך גישה חכמה יותר.
אנחנו מחלקים את הסריקה לשכבות. 'שכבת הזהב' כוללת את המוצרים הפופולריים ביותר או אלו שמשתנים בתדירות גבוהה. אותם אנחנו סורקים כל 1-2 שעות. 'שכבת הכסף', שכוללת את רוב הקטלוג, נסרקת פעם ב-24 שעות. 'שכבת הארד', תוכן ישן או זניח, נסרקת פעם בשבוע. המיפוי הזה דורש ניתוח ראשוני, אבל הוא מצמצם את העומס על המערכת ועל האתר בכ-80%. כדי לנהל את כל זה, אנחנו משתמשים ב-message queue כמו RabbitMQ או SQS. כל משימת סריקה (URL או קריאת API) נכנסת לתור עם תעדוף מתאים. ה-workers לוקחים משימות מהתור, מבצעים אותן, ומכניסים את התוצאה לדאטהבייס. גישה זו מאפשרת סקיילביליות אופקית קלה. אם צריך קצב גבוה יותר, פשוט מוסיפים עוד workers. זהו המפתח למערכת מעקב מלאי/זמינות yes שאינה רק אוספת נתונים, אלא עושה זאת ביעילות.
מתי לא כדאי להשתמש ב-API הפנימי
אחרי כל מה שאמרתי, יש מצבים שבהם ההתמקדות ב-API הפנימי היא טעות. זה קורה כשהאתר מיישם הגנות מתקדמות שקושרות את קריאות ה-API לסשן של הדפדפן בצורה מתוחכמת. למשל, אם כל קריאת API דורשת token שנוצר על ידי לוגיקת JavaScript מורכבת ומעורפלת (obfuscated) שמשתנה כל כמה שעות. במצב כזה, ניסיון לעשות reverse engineering לקוד הזה הוא בור ללא תחתית. זה קרב שקשה לנצח בו, והתחזוקה הופכת לסיוט.
במקרים אלו, אנחנו חוזרים אחורה לגישת הדפדפן המלא עם Playwright, אבל עם שכבת תחכום נוספת. במקום ליירט את ה-API, אנחנו נותנים לדף להיטען במלואו ורק אז מחלצים את הנתונים מה-DOM. כן, זה איטי יותר משמעותית. אבל זה גם הרבה יותר יציב. כדי להתמודד עם האיטיות, מריצים עשרות מופעי דפדפן במקביל. כדי להתמודד עם זיהוי, משתמשים בטכניקות מתקדמות. זה המקום שבו מדריך Playwright stealth הופך להיות קריטי. הוא מסביר איך להסוות את העובדה שאתה דפדפן אוטומטי. לפעמים, הדרך הישירה והאיטית היא הדרך המהירה ביותר לתוצאה יציבה. לדעת מתי לוותר על אופטימיזציית ה-API זו חוכמה שנרכשת בניסיון.
מודיעין מתחרים ואינטגרציה: מה עושים עם הדאטה?
איסוף הנתונים הוא רק חצי מהסיפור. הערך האמיתי נוצר כשמשתמשים בו. עבור מודיעין מתחרים yes, הנתונים שנאספו צריכים להיות מנורמלים ומועשרים. זה אומר להפוך שמות מבצעים ושדות טקסט חופשי למבנה קבוע שאפשר להשוות לאורך זמן ומול מתחרים. למשל, לזהות אוטומטית מבצעי 'הצטרפות', 'שדרוג' או 'חבילת תוכן' ולהקצות להם קטגוריות.
השלב הבא הוא בניית מערך התראות. לדוגמה, התראה אוטומטית שמופעלת בכל פעם שמתווסף ערוץ חדש לחבילה מסוימת, או כשמחיר של סרט VOD יורד מתחת לרף מסוים. זה מאפשר תגובה מהירה לשינויים בשוק. בסופו של דבר, המטרה היא לא טבלאות של מידע גולמי, אלא פיד נתונים מעובד. לקוחות וצוותים פנימיים צריכים לצרוך את המידע דרך API פנימי, קובץ CSV שבועי שנוחת ב-S3, או דשבורד ויזואלי. בניית צינור הנתונים הזה, מהאיסוף ועד לצריכה, היא האתגר ההנדסי המלא. חשוב מאוד להבין את הצרכים של משתמשי הקצה כדי לתכנן נכון את סכמת הנתונים. אם אתם נתקלים בחסימות רשת תכופות, כדאי לקרוא על איך לבחור פרוקסי residential כדי לשמור על זרימת נתונים רציפה.
