למה requests.get נופל על הצעד הראשון ב-Careerjet

בואו נשים את זה על השולחן: אם הגישה שלכם ל-scraping Careerjet Israel מתחילה ונגמרת ב-requests.get(url), אתם מבזבזים את הזמן שלכם. כשתריצו את זה, תקבלו HTML, אבל כנראה שלא תמצאו בו את רשימת המשרות. למה? כי התוכן המרכזי נטען דינמית באמצעות JavaScript לאחר טעינת הדף הראשונית. זהו המכשול הראשון והבסיסי ביותר.

הפתרון המיידי שעולה לראש הוא להשתמש בכלי שמריץ דפדפן אמיתי, כמו Playwright או Puppeteer. תשכחו מ-Selenium לפרויקטים חדשים. Playwright מנצח אותו ב-2025 בכל מטריקה רלוונטית, מהביצועים ועד ה-API. שימוש בדפדפן פותר את בעיית ה-JS rendering ומאפשר לנו לגשת ל-DOM המלא, בדיוק כפי שהמשתמש רואה אותו. זה קריטי עבור המשימה הראשונית של איסוף קטלוג Careerjet Israel – מיפוי כל המשרות הזמינות. אבל פה הסיפור רק מתחיל. עצם השימוש בדפדפן חושף אותנו למערך חדש של אתגרים: זיהוי בוטים מבוסס התנהגות, טביעות אצבע של הדפדפן (fingerprinting), וניהול משאבים. הרצת אלף טאבים של כרום היא לא עניין של מה בכך. לכן, הבחירה בכלי הנכון היא רק 10% מהעבודה; 90% הנותרים הם איך משתמשים בו נכון כדי לא להיראות כמו רובוט רועש.

ארכיטקטורת ה-Scraper הנכונה: Playwright וניהול סשנים

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

ארכיטקטורה שעובדת טוב במקרים כאלה מבוססת על 'עובדים' (workers) שמחזיקים קונטקסט דפדפן (browser context) לאורך זמן. כל עובד מקבל IP ייחודי דרך פרוקסי ומדמה משתמש שונה. הוא לא רק מבקר בדף התוצאות, אלא מבצע 'חימום' – מנווט לדף הבית, אולי מבצע חיפוש או שניים, ורק אז מתחיל לאסוף נתונים. גישה זו מאפשרת לנו לאסוף מידע בצורה עקבית, למשל, לחלץ שדות כמו שמות מוצרים/מודעות וקטגוריות בצורה מדויקת. ראינו הצלחה עם עובדים שחיים בין 10 ל-30 דקות, עם רוטציה של פרוקסי איכותי. זה מייקר את המורכבות התפעולית אבל מקפיץ את אחוזי ההצלחה מ-70% ל-98% ומעלה, והופך את תהליך איסוף הנתונים לצפוי ואמין הרבה יותר.

סקייל: איך שורדים 50,000 בקשות ביום בלי להיחסם

איסוף דף אחד זה קל. מה קורה כשצריך לאסוף את כל 2,500 דפי התוצאות של Careerjet Israel, בכל יום, כדי לספק API / קובץ נתונים עדכני? כאן אנחנו נכנסים לעולם של scraping בקנה מידה גדול. הבעיה המרכזית היא rate limiting. אם תשלחו 500 בקשות מדקה אחת מאותו IP, אתם תחסמו. זה מובטח.

הפתרון הוא שילוב של שלוש טכניקות: Proxy Rotation, Concurrency חכם, ו-Throttling. ראשית, אתם צריכים מאגר גדול של פרוקסי'ס, רצוי residential. איך לבחור פרוקסי residential זה נושא בפני עצמו, אבל הנקודה היא שכל בקשה או קבוצת בקשות קטנה צריכה להגיע מכתובת IP שונה. שנית, במקום להריץ בקשות באופן סדרתי, תשתמשו ב-async IO כדי להריץ עשרות 'עובדים' במקביל. עם ארכיטקטורה נכונה, אפשר להגיע לקצב של 1,000 דפים בדקה בלי להעמיס על המערכת. שלישית, וזה החלק החשוב, תטמיעו throttling דינמי. אם אתם מתחילים לקבל יותר מדי שגיאות 429 או CAPTCHAs, המערכת צריכה להאט את הקצב אוטומטית. זהו משחק של חתול ועכבר: המטרה היא למצוא את הקצב המקסימלי שהאתר מאפשר בלי לזהות אתכם כפעילות זדונית. זה לא מספר קבוע, הוא משתנה בהתאם לעומס על השרתים שלהם ולפרמטרים נוספים.

התרחיש ששובר כל סקרייפר: Pagination נסתר ו-Data Freshness

הנה תרחיש כשל קלאסי שראיתי קורס שוב ושוב באתרים כמו Careerjet Israel. המהנדס בונה סקרייפר שעובר על כל דפי ה-pagination, מ-1 עד 250, ואוסף את כל המשרות. זה עובד נהדר במשך שבוע. ואז, הנתונים מתחילים להיות לא מדויקים. משרות שנסגרו עדיין מופיעות בדאטהבייס, ומשרות חדשות לא תמיד נכנסות. מה קרה?

הבעיה היא ש-pagination לינארי הוא אשליה. בזמן שהסקרייפר שלכם רץ (וזה יכול לקחת שעה), משרות חדשות נוספו לדפים הראשונים, ודחפו את כל שאר התוצאות קדימה. כשהסקרייפר מגיע לדף 150, הוא למעשה אוסף משרות שכבר ראה בדף 149 בריצה הקודמת, ומפספס את המשרות ש'נפלו' מהסוף. זה קריטי במיוחד עבור מעקב מלאי/זמינות של משרות. הדרך הנכונה להתמודד עם זה היא לא לסמוך על מספרי עמודים, אלא לעבוד עם מזהה ייחודי של המשרה האחרונה שראיתם, או להשתמש בפרמטרים של תאריך בחיפוש כדי לצמצם את טווח הזמן. גישה נוספת היא להריץ סריקות מהירות וממוקדות על הדפים הראשונים בתדירות גבוהה יותר, וסריקה מלאה ועמוקה בתדירות נמוכה יותר. בלי אסטרטגיה כזו, אתם פשוט אוספים נתונים 'מעופשים' שהערך שלהם הולך ויורד.

מתי הנתונים מ-Careerjet Israel פשוט לא מספיקים

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

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