במדריך זה נלמד כיצד לבצע גירוד נתונים מאתרים (Web Scraping) באמצעות סלניום (Selenium) בשפת פייתון

סלניום? נעים מאוד! 👋

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

  • בדיקות אוטומטיות - סלניום יכולה להפוך את תהליך הבדיקה של יישומי אינטרנט לאוטומטיים. אתה יכול לכתוב סקריפטים המחקים את האופן שבו משתמשים מקיימים אינטראקציה עם האתר, בודקים פונקציונליות ומזהים באגים כלשהם.
  • גירוד נתונים - ניתן להשתמש בסלניום כדי לחלץ נתונים מאתרים. מה שמאפשר לנו לאסוף מידע על מוצרים, מחירים ולמעשה כל מה שרק נרצה.
  • גירוד אתרים שלמים - בדומה לגרידת נתונים, ניתן להשתמש בסלניום בכדי להעתיק דפי אינטרנט שלמים או חלקים ספציפיים של דף אינטרנט ולאחסן אותם איפה ואיך שרק נרצה
  • סלניום עובדת עם שפות תכנות רבות - ניתן להריץ את סלניום בסביבת Python, Java ו-C#. היא חינמית לגמרי ויש לה קהילת מפתחים ענקית אשר מספקת לה תמיכה ומשאבי מידע שונים.
    כל היתרונות הללו הופכים את סלניום (המזדקנת) לסוס בלתי מנוצח. במדריך זה נעבוד עם סלניום בסביבת פייתון בלבד.

התקנת סלניום

קודם כל עלינו לוודא ש-Python 3 מותקן ומעודכן. לאחר מכן, נפתח את המסוף או CMD ונכתוב:

pip install selenium

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

צעדים ראשונים- בואו נתחיל

בהנחה שסלניום כבר מותקנת, נפתח את עורך הפיתון שלנו ונחלץ כותרת של עמוד:

from selenium import webdriver

## כבר אין צורך לעבוד עם webdrivers חיצוניים
driver = webdriver.Firefox()

## ניתן להשתמש בכל דפדפן שמותקן על גבי המחשב
driver.get("https://מדעןנתונים.ישראל")

## נעתיק את כותרת האתר ונדפיס אותה למסך:
title = driver.title
print(title[::-1])

## אם הכל תקין, הפקודה הבאה תסגור את הדפדפן:
driver.close()

איפה אני יכול להוריד את מנהלי ההתקנים (WebDrivers) לדפדפן?

חדשות טובות! מאז גרסה 4.6, החיבור לדפדפנים אינו מצריך עוד הגדרה ידנית של WebDrivers. מה שחוסך כמות משמעותית של זמן, במיוחד אם שרפתם יותר משעה כדי להבין למה הם כבר לא עובדים (כמוני)😂.

גישה לאלמנטים

הגישה לאלמנטים המוטמעים בדף אינטרנט הינה חיונית עבור משימות רבות.
כדי לבדוק את ה-HTML, עלינו ללחוץ באמצעות לחצן העכבר הימני בכל מקום בדף האינטרנט ולבחור “חקור אלמנט” או “צפיה בקוד מקור”. ישנן שלוש דרכים עיקריות לזהות אלמנטים בדף אינטרנט: מזהה יחודי (ID) , שם מחלקה (Class Name), ו-שם (בדרך כלל ייחודי). כאשר אנו רוצים לגשת לרכיב ספציפי, עדיף להשתמש ב-ID מכיוון שהוא מבטיח שנבחר את הרכיב המדויק שאנחנו רוצים להעתיק. כשאנחנו משתמשים במחלקות או בשמות שאינם יחודיים אנחנו למעשה מרחיבים את אפשרויות הבחירה שלנו ולרוב נעשה זאת כשאנחנו רוצים לייצר לולאה שתעתיק תוכן רב יותר ולא פריט ספציפי.

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

from selenium import webdriver
from selenium.webdriver.common.by import By
import time

driver = webdriver.Chrome()
## You can call to any browser that installed on your device.
driver.get("https://מדעןנתונים.ישראל/search/")
title = driver.title
print(title[::-1])

search = driver.find_element(By.ID, "searchInput").send_keys("זאת סתם בדיקה")

time.sleep(5)

driver.quit()

על מנת לגשת לאלמנט אנו משתמשים במתודה שנקראת find_element לפי הקונבנציה הבאה: something.find_element(attributes, what we're looking for)

סוגים של תכונות (attributes)

בעבודה עם מתודה find_element ישנם אטריביוטים (תכונות) המאפשרות לנו להגדיר מהו הפריט שאנחנו אליו רוצים לגשת,
אלו התכונות הזמינות נכון לכתיבת שורות אלו:

ID = "id"
NAME = "name"
XPATH = "xpath"
LINK_TEXT = "link text"
PARTIAL_LINK_TEXT = "partial link text"
TAG_NAME = "tag name"
CLASS_NAME = "class name"
CSS_SELECTOR = "css selector"

קונבנציה

הקונבנציה בתוך הסוגריים הולכת כך: (By.NAME, "What i'm looking for").
לדוגמא, אם אני מחפש מחלקה בשם “Search_Box” אכתוב את הפונקציה הבאה: (By.CLASS_NAME, "Search_Box").

ביצוע פעולות 🪖

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

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.expected_conditions import presence_of_element_located
from selenium.webdriver.support.ui import WebDriverWait 
import time

##It is no longer necessary to install 3rd webdriver.
driver = webdriver.Chrome()
## You can call to any browser that installed on your device.
driver.get("https://מדעןנתונים.ישראל/search/")

search = driver.find_element(By.ID, "searchInput")
search.send_keys("ABC")

# Define the expected link text (more reliable than using a long string literal)
expected_link_text = "מדען נתונים"
try:
    wait = WebDriverWait(driver, 20)  # Wait for up to 20 seconds - things should be loading. 
    link = wait.until(presence_of_element_located((By.LINK_TEXT, expected_link_text))) #Wait and then search where's the link with this text.
    link.click() 
    time.sleep(15)
except:
    print("Link not found or clickable within 10 seconds.")

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

  1. טיפול בשגיאות: דברים יכולים להיות בלתי צפויים באתרי אינטרנט, בדיוק כמו בעולם האמיתי. הבלוק try הוא המקום שבו הקוד שלנו מנסה למצוא את מה שהוא התבקש. ובמידה והוא לא הצליח במקום שכל התוכנית תקרוס, פשוט תודפס השגיאה שהגדרנו לו מבעוד מועד.
  2. משפר את יציבות הסקריפט: כשהדברים משתבשים הקוד לא קורס ובמקום זה תודפס הודעה או שתתבצע פעולה אחרת שהגדרנו מבעוד מועד.

שליפת נתונים

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

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.expected_conditions import presence_of_element_located
from selenium.webdriver.support.ui import WebDriverWait 
import csv

# Replace with your website URL and element locators
driver = webdriver.Chrome()
driver.get("http://מדעןנתונים.ישראל/")

# Find elements containing data
wait = WebDriverWait(driver, 10)  # Wait for up to 10 seconds
link = wait.until(presence_of_element_located((By.CLASS_NAME, "entry-header")))

elements = driver.find_elements(By.CLASS_NAME, "entry-header")


# Print elements to check if they are being located correctly
print("Number of elements found:", len(elements))
for element in elements:
    print(element.text)

# Extract data and store in a list of lists
data = []
for element in elements:
    row = [element.text]  # Example data extraction
    data.append(row)

driver.quit()  # Close the browser
print(data)
# Export data to CSV

with open('scraped_data.csv', 'w', newline='', encoding='utf-8') as csvfile:
    writer = csv.writer(csvfile)
    writer.writerow(data)  # Adjust headers as needed
    for row in data:
        writer.writerow(row)

print("Data exported to scraped_data.csv")

מילות סיכום

אם הצלחתם להגיע עד כאן, כל הכבוד לכם! במדריך הזה עשינו את הצעדים הראשונים בעולם שליפת הנתונים עם Selenium ו-Python.
אני מקווה שנהניתם מהמסע ולמדת משהו בעל ערך. יש היום כלי נוסף מדהים לא פחות שמאפשר לנו לבצע גירוד נתונים (מין תרגום מוזר כזה ל-Data Scraping) כמו Beautiful Soup, אני מתכנן לכתוב גם עליו מדריך בהמשך.
יחד עם זה, סלניום עם כמה שהיא ותיקה היא עדיין נחשבת לכלי הנפוץ והאמין ביותר.
מדעני נתונים רבים ברחבי העולם בוחרים לעשות בה שימוש יומיומי ואני בהחלט מאמין שככל שנעמיק בכתיבה שלה כך גם הקוד שלנו באופן כללי ישתפר. מקווה שלמדתם משהו חדש היום. מוזמנים לשתף :)