למה ה-Network Tab הוא הכלי החשוב ביותר לסקרייפר?
בואו נשים את הדברים על השולחן. אם אתם עדיין חושבים ש-web scraping זה רק להוריד HTML ולעשות לו parsing עם BeautifulSoup, אתם עובדים בשיטות של 2015. זה עובד לאתרים פשוטים, אבל רוב האתרים המודרניים כבר לא שם.
היום, רוב התוכן הדינמי שאתם רואים נטען אסינכרונית. אתם לוחצים על כפתור, מחילים פילטר, או גוללים למטה, והדפדפן לא טוען עמוד חדש. במקום זה, קוד JavaScript שולח בקשת רשת (בדרך כלל ל-API), מקבל בחזרה מידע נקי בפורמט JSON, ורק אז מעדכן את ה-HTML שאתם רואים. זה נקרא Single Page Application (SPA), וזה הסטנדרט.
הזהב האמיתי נמצא בבקשות ה-API האלה. למה? כי במקום להתמודד עם HTML מסורבל ומשתנה, אתם מקבלים גישה ישירה למקור הנתונים. זה מהיר יותר, אמין יותר, ודורש פחות תחזוקה. ה-DevTools Network tab הוא המפה שלכם לאוצר הזה. שם אתם יכולים לראות כל בקשה ובקשה שהדפדפן שולח, לנתח אותה, ולהבין איך לשכפל אותה בקוד שלכם. שליטה בכלי הזה היא ההבדל בין חובבן למקצוען.
סיור מהיר בכלים החיוניים ב-DevTools Network
כשפותחים את ה-Network tab (עם F12 או Cmd+Option+I), קל ללכת לאיבוד. יש עשרות בקשות, גרפים, ונתונים. אבל 90% מהזמן, אתם תצטרכו רק כמה כלים ספציפיים. בואו נתמקד בהם.
הפיצ'רים הבסיסיים שחובה להכיר
- Preserve log: התיבה הזו קריטית. כשהיא מסומנת, יומן הבקשות לא נמחק כשאתם עוברים בין עמודים. זה חיוני כדי לעקוב אחרי תהליכי login, הפניות (redirects), או כל פעולה שכוללת יותר מעמוד אחד.
- Disable cache: סמנו אותה תמיד. אתם רוצים לראות את מה שמשתמש חדש רואה, לא גרסה שהדפדפן שלכם שמר בזיכרון. זה מונע שעות של דיבאג מתסכל שבו אתם לא מבינים למה הקוד שלכם לא עובד בזמן שהדפדפן כן.
- שורת הפילטרים: כאן קורה הקסם. במקום לבהות במאות בקשות לתמונות, פונטים ו-CSS, אתם יכולים לסנן. הפילטרים הכי שימושיים לסקרייפרים הם:
- Fetch/XHR: זה הפילטר החשוב ביותר. הוא מציג רק בקשות API אסינכרוניות ש-JavaScript יזם. ב-99% מהמקרים, ה-JSON שאתם מחפשים יתחבא כאן.
- Doc: מציג רק את בקשת ה-HTML הראשית של העמוד. שימושי כדי לראות את ה-headers הראשוניים או את ה-HTML הבסיסי שהשרת מחזיר.
- JS: לפעמים צריך לצלול לקוד ה-JavaScript עצמו כדי להבין איך בקשת API נבנית. נדבר על זה בהמשך.
ה-Workflow המנצח: מזיהוי הבקשה ועד לקוד עובד
פיתחתי לעצמי תהליך עבודה קבוע שעובד כמעט תמיד. הוא מורכב מארבעה שלבים פשוטים, והוא חוסך לי המון זמן.
שלב 1: בידוד הפעולה
פתחו את ה-Network tab. נקו את היומן (כפתור הניקוי, עיגול עם קו חוצה). עכשיו, בצעו בדיוק את הפעולה שאתם רוצים לחקות. למשל, לחיצה על כפתור "טען עוד מוצרים". אל תזיזו את העכבר סתם, אל תגללו. רק הפעולה הספציפית. תראו איך רשימת הבקשות מתמלאת. סננו לפי Fetch/XHR.
שלב 2: איתור בקשת המטרה
עברו על הבקשות שצצו. חפשו שמות הגיוניים כמו `api/products`, `get_listings`, או משהו דומה. לחצו על כל אחת ובדקו את לשונית ה-`Preview` או `Response`. אם אתם רואים שם JSON עם הנתונים שחיפשתם (שמות מוצרים, מחירים) — מצאתם את המטרה.
שלב 3: ניתוח הבקשה ו-Copy as cURL
עכשיו, לכו ללשונית `Headers`. כאן נמצא המידע החשוב: כתובת ה-URL המדויקת, מתודת ה-HTTP (GET/POST), וכל ה-Request Headers. שימו לב ל-headers מיוחדים כמו `Authorization`, `X-CSRF-Token`, או `x-api-key`. הם המפתחות שלכם. אם זו בקשת POST, בדקו גם את ה-`Payload` כדי לראות איזה מידע נשלח.
ברגע שזיהיתם את הבקשה, לחצו עליה קליק ימני ובחרו `Copy` > `Copy as cURL`. הפקודה הזו היא ייצוג טקסטואלי מושלם של הבקשה, כולל ה-URL, ה-headers, ה-cookies וה-payload. הדביקו אותה בטרמינל והריצו. אם קיבלתם את אותו JSON בחזרה — הצלחתם לשכפל את הבקשה מחוץ לדפדפן.
# דוגמה לפקודת cURL שהועתקה מהדפדפן
curl 'https://api.example.com/v2/products?page=2&sort=price' \
-H 'accept: application/json' \
-H 'authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...' \
-H 'user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) ...' \
--compressed
שלב 4: תרגום לקוד
השלב האחרון הוא להפוך את פקודת ה-cURL לקוד Python עם ספריית `requests`. אתם יכולים לעשות את זה ידנית או להשתמש בכלים כמו curlconverter.com. התוצאה תהיה משהו כזה:
import requests
headers = {
'accept': 'application/json',
'authorization': 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) ...',
}
params = {
'page': '2',
'sort': 'price',
}
response = requests.get('https://api.example.com/v2/products', params=params, headers=headers)
if response.status_code == 200:
data = response.json()
print(data)
else:
print(f"Failed with status code: {response.status_code}")
זהו. יש לכם סקרייפר שעובד ישירות מול ה-API. הוא מהיר פי 100 מכל פתרון מבוסס דפדפן, והרבה יותר יציב.
אבל רגע — זה לא תמיד כל כך פשוט
ה-workflow שתיארתי עובד ב-70% מהמקרים. אבל מהנדס סקרייפינג מנוסה נמדד ביכולת שלו להתמודד עם ה-30% הנותרים. הנה תרחיש כשל קלאסי: העתקתם את ה-cURL, הוא עבד פעם אחת מהמחשב שלכם, אבל כשהרצתם אותו מהשרת או אחרי 5 דקות, הוא נכשל עם שגיאת 401 Unauthorized או 403 Forbidden.
מה קרה? כנראה נתקלתם בהגנה דינמית. הנה כמה סיבות נפוצות:
- טוקנים קצרי מועד: ה-`Authorization` header שהעתקתם הכיל טוקן (כמו JWT או CSRF) שתקף רק לכמה דקות. כדי לפתור את זה, אתם צריכים למצוא את הבקשה שמייצרת את הטוקן (לרוב בקשת ה-login או בקשת ה-HTML הראשית) ולהריץ אותה קודם כדי לקבל טוקן טרי.
- חתימות תלויות IP או סביבה: לפעמים השרת מייצר חתימה או טוקן שקשורים לכתובת ה-IP שלכם או ל-headers אחרים. כשאתם מנסים להריץ את הבקשה משרת עם IP אחר, החתימה לא תואמת והבקשה נדחית. במקרים כאלה, חובה להריץ את כל התהליך (קבלת טוקן ושליחת בקשה) מאותו ה-proxy.
- טביעת אצבע של הדפדפן (Fingerprinting): זו הרמה הבאה של ההגנות. קוד JavaScript בדף אוסף עשרות פרמטרים על הדפדפן שלכם (פונטים, רזולוציה, גרסת דפדפן) ויוצר מהם hash ייחודי. ה-hash הזה נשלח כ-header בבקשת ה-API. אם תשלחו את הבקשה עם `requests`, ה-header הזה יהיה חסר והשרת יחסום אתכם. כאן, אין מנוס משימוש ב-Headless browser כמו Playwright, ולעתים קרובות תצטרכו כלים נוספים כמו Playwright-stealth כדי לעקוף זיהויי בוטים.
טכניקות מתקדמות לדיבאגינג וסימולציה
כשהדברים מסתבכים, ה-DevTools מציע עוד כמה כלים מתקדמים שיכולים להציל את המצב.
סימולציה של רשתות איטיות (Throttling)
בתפריט ה-Throttling, אתם יכולים לדמות חיבור אינטרנט איטי (כמו "Slow 3G"). למה זה שימושי? לפעמים אתרים מגישים גרסה קלה ופשוטה יותר של האתר או ה-API למשתמשים עם חיבור איטי. סימולציה כזו יכולה לחשוף endpoint נסתר וקל יותר לגירוד. זה גם עוזר להבין איך האתר מתנהג כשהבקשות לא חוזרות מיד.
חסימת בקשות (Request Blocking)
קליק ימני על בקשה כלשהי מאפשר לכם לחסום אותה (`Block request URL`) או את כל הדומיין שלה (`Block request domain`). זה כלי אדיר לבידוד. חושדים שסקריפט אנליטיקה מסוים מפריע לכם? חסמו אותו. רוצים לראות אם האתר עובד בלי קבצי CSS או תמונות? חסמו את הדומיינים שלהם. זה מאפשר לכם לנקות את הרעש ולהתמקד רק בבקשות החיוניות לתהליך שאתם מנסים להנדס לאחור.
ניתוח קבצי HAR
אתם יכולים לייצא את כל סשן הרשת לקובץ בפורמט HAR (HTTP Archive) על ידי לחיצה על כפתור הייצוא (חץ למטה). קובץ ה-HAR הוא JSON ענק שמכיל כל פרט ופרט על כל בקשה ותגובה. זה שימושי מאוד לדיבאגינג אופליין, לשיתוף הבעיה עם קולגות, או להזנת נתונים לכלים אוטומטיים שיודעים לנתח את תהליך התקשורת. זה כמו צילום רנטגן של כל מה שהדפדפן עשה.
מתי להשתמש ב-Headless Browser ומתי ב-Requests?
זו שאלת מיליון הדולר, והתשובה תלויה במה שגיליתם ב-Network tab. הכלל שלי פשוט:
התחילו תמיד עם ההנחה שאפשר להשתמש ב-`requests` (או כל HTTP client אחר). זה תמיד יהיה הפתרון המהיר, הזול והיציב ביותר. עברו על ה-workflow שתיארתי: מצאו את ה-API, שכפלו את הבקשה, ונסו להפוך אותה לאוטומטית. אם הצלחתם, מעולה. זה המצב האידיאלי, במיוחד כשצריך לבנות ארכיטקטורת סקרייפינג בסקייל גבוה.
עברו ל-Headless Browser (כמו Playwright או Selenium) רק כשאתם חייבים. מתי זה קורה? כשניתוח הרשת מגלה שהבקשות חתומות על ידי JavaScript מורכב שאתם לא יכולים או לא רוצים להנדס לאחור. אם אתם רואים headers עם ערכים שנראים כמו hash-ים ארוכים ורנדומליים, או אם הבקשה פשוט לא עובדת מחוץ לדפדפן לא משנה מה ניסיתם, זה הזמן להרים דגל לבן ולהביא את התותחים הכבדים. דפדפן אמיתי יריץ את ה-JavaScript, ייצר את החתימות הנדרשות, וישלח בקשות תקינות. המחיר הוא ביצועים איטיים בהרבה וצריכת משאבים גבוהה, אבל לפעמים אין ברירה.
ה-DevTools Network הוא הגשר בין שתי הגישות האלה. הוא הכלי שיגיד לכם באיזו דרך לבחור, ויחסוך לכם שבועות של עבודה מיותרת.
שאלות נפוצות
כדי להתמודד עם גלילה אינסופית, פתח את ה-DevTools Network tab וסנן לפי Fetch/XHR. גלול למטה בדף וצפה בבקשות החדשות שמופיעות. בדרך כלל תראה בקשת API שחוזרת על עצמה עם פרמטר שונה בכל פעם, כמו `page=2`, `page=3`, או `offset=50`. לאחר שזיהית את התבנית, תוכל לשכפל את הבקשה הזו בקוד שלך בלולאה, תוך כדי הגדלת ערך הפרמטר בכל איטרציה, וכך לאסוף את כל הנתונים בלי לדמות גלילה בדפדפן.
לשונית ה-Payload מציגה את המידע שהדפדפן *שלח* לשרת, ורלוונטית בעיקר לבקשות POST, PUT או PATCH. היא מראה את הנתונים, בדרך כלל בפורמט JSON או Form Data, שנשלחו בגוף הבקשה. לעומת זאת, לשונית ה-Preview (וגם ה-Response) מציגה את המידע שהשרת *החזיר* בתגובה. ה-Preview מנסה לעצב את התגובה בצורה קריאה, למשל להציג עץ JSON אינטראקטיבי, בעוד שה-Response מציגה את הטקסט הגולמי כפי שהתקבל מהשרת.
שגיאת 403 Forbidden לאחר העתקת cURL מצביעה בדרך כלל על מנגנון אבטחה שחסר בבקשה המשוכפלת. סיבה נפוצה היא header חסר או לא תקין, כמו `X-CSRF-Token`, `Referer`, או טוקן `Authorization` שפג תוקפו. סיבה נוספת יכולה להיות שהשרת מצפה שהבקשה תגיע מאותו IP שממנו נטען הדף המקורי, והרצת ה-cURL מהטרמינל או משרת אחר נכשלת. בדוק היטב את כל ה-headers בבקשה המקורית והשווה אותם לאלו שבפקודת ה-cURL.
כדי למצוא קוד JavaScript שמייצר header ספציפי, השתמש בלשונית ה-`Sources` ב-DevTools. בחלונית הימנית, תחת `XHR/fetch Breakpoints`, לחץ על סימן הפלוס והוסף breakpoint שיעצור את ריצת הקוד רגע לפני שליחת בקשת XHR. לחלופין, השתמש בחיפוש הגלובלי (Ctrl+Shift+F) וחפש את שם ה-header החשוד (למשל `X-Request-Signature`). זה יעזור לך לאתר את שורות הקוד שבהן ה-header מוגדר, ומשם תוכל לנתח את הלוגיקה שלו.
קובץ HAR (HTTP Archive) הוא פורמט JSON סטנדרטי שמתעד את כל האינטראקציה בין הדפדפן לשרת. אתה יכול לייצא אותו מה-Network tab. קובץ HAR שימושי מאוד לדיבאגינג מורכב, מכיוון שהוא מאפשר לך לנתח את כל רצף הבקשות והתגובות בצורה לא מקוונת. לדוגמה, אם יש תהליך login מורכב עם מספר הפניות ובקשות, תוכל לייצא את התהליך המוצלח כ-HAR, לנתח אותו, ולשכפל את הרצף המדויק של הבקשות וה-headers בקוד שלך, כמו בספריית `requests-har` בפייתון.
