בסיס שימוש באינטרנט עם פייתון


בסיס

אתחול

אחד מהשימושים היותר יפים של פייתון הוא לאיסוף ושימוש בפקודות לאינטראקציה עם האינטרנט. ראשית, נצטרך להוריד 3 ספריות על מנת להשתמש בפונקציונליות זו. הספריות הינן, beautifulsoup4, requests, lxml כבר הכינותי מראש מדריך התקנה של חבילות (כאן). כעת לאחר שהתקנו אותן, נשים לב שצריך לאמר לפייתון שנשתמש בהן בסקריפט. נזמנם על ידי רשימת השורות הללו בראש הסקריפט –

from bs4 import BeautifulSoup
import requests

לקיחת מידע מאתר דרך קוד HTML

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

from bs4 import BeautifulSoup
import requests
____
source = requests.get('https://www.youtube.com/feed/trending').text
soup = BeautifulSoup(source,'lxml')
print(soup)

פעולה זו כנראה תיקח כמה זמן, ובסופה, אמור להיות מודפס הhtml של אתר זה (כנראה שתראו הערה שההדפסה מכילה הרבה שורות והם אתם רוצים להראותה בכל מקרה, תאשרו כדי לבדוק שאכן זה עבד). עכשיו אסביר קצת על הקוד, פעולת הrequest בעצם מביאה לנו סטרינג של קוד הhtml, ובעזרת אובייקט הsoup נטמיע את הקוד באובייקט הבנוי להכלת הקוד הגולמי, וגישה אליו בצורה נוחה.

שימוש במידע

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



מה שבעצם נעשה זה נלחץ מקש ימני על האלמנט שנרצה לחלץ, ונקליק על בדוק רכיב, והקונסולה תראה לנו היכן רכיב זה נמצא בקוד. כעת, נראה כי שמות הסרטונים נמצאים בתוך רכיב בשם yt-formatted-string, נאתרו בפונקציית הfind. כך –

from bs4 import BeautifulSoup
import requests
____
source = requests.get('https://www.youtube.com/feed/trending').text
soup = BeautifulSoup(source,'lxml')
vtitle = soup.find('yt-formatted-string')
print(vtitle)

אבל, במידה ונעשה זאת, נקבל בחזרה none, כלומר שערך זה לא נמצא. אם נעשה בלשנות, נגלה שלא עשינו אף טעות, ובאמת, לא נמצא את הערך הזה בסטרינג הhtml שהתקבל מהבקשה. כעת, נבדוק מהו הסטרינג הלא תואם לכאורה שהתקבל מהבקשה. (הערה: על מנת לעשות זאת נוכל פשוט להעתיק את הסטרינג, אחרי שנדפיסו, נשים אתו בnotepad, נשמורו בסיומת html, ונפתח אותו עם דפדפן.) המסך שהתקבל הינו –



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

אז יש לנו שתי אופציות, לעבוד עם החומר שיש לנו, או לבצע את עבודת הדפדפן. כעת, עקב כך שמה שאנו עושים זה רק לקיחת שמות פשוטה, נוכל להסתפק במצוי. אחרי הכל לא צריך חללית כדי להגיע לאשקלון. אז במקום לחקור את הקוד דרך כרום, נחקור את אותו הסטרינג שהתקבל מהבקשה. ונראה בתמונה שלמעלה, ששרכיב שם הסרטון נמצא בa, שקלאס הhtml שלו הוא yt-uix-tile… וכעת נמצאו , כך –

from bs4 import BeautifulSoup
import requests
____
source = requests.get('https://www.youtube.com/feed/trending').text
soup = BeautifulSoup(source,'lxml')
vtitle = soup.find('a' , class_='yt-uix-tile-link yt-ui-ellipsis yt-ui-ellipsis-2 yt-uix-sessionlink spf-link')
print(vtitle.text)

ונראה שבאמת התקבל שם השיר.

Find

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

<a aria-describedby="description-id-420697" class="yt-uix-tile-link yt-ui-ellipsis yt-ui-ellipsis-2 yt-uix-sessionlink spf-link" data-sessionlink="itct=CEwQ3DAYACITCJb1367Pq-gCFfvs5godIe4ElDIKZy1oaWdoLXRydloKRkV0cmVuZGluZw" dir="rtl" href="/watch?v=NwDvbCkwGXo" title="אייל גולן - מכאן ועד הנצח">אייל גולן - מכאן ועד הנצח</a>
vtitle = soup.find('a' , class_='yt-uix-tile-link yt-ui-ellipsis yt-ui-ellipsis-2 yt-uix-sessionlink spf-link')

על מנת לאתר את הרכיב, נסתמך על כך שלכל רכיב בhtml יש מאפיינים מסויימים. למשל לרכיב שמצאנו יש את המאפיינים, aria-describedby, class, data-sessionlink, dir, title , וכמובן את סוג הרכיב עצמו a . ובעצם נאכיל את הפונקצייה find במאפיינים, דרכיהם היא תמצא את הרכיב שאנו חפצים בו. את סוג הרכיב נשים ראשון, ואחריו את שאר המאפיינים, דרך מילון. כך שהערך ראשון הוא שם המאפיין, והערך ההשני הוא ערך המאפיין –

vtitle = soup.find('a' , {'href' : '/watch?v=NwDvbCkwGXo'})

Find_all

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

האובייקט הנלקח

כשמתכננים לקיחת עצמים, כדאי לתכנן את הלקיחה נכון. אדגים את התכנון על ידי סוף כל סוף ביצוע המטלה שלנו. דבר ראשון אבחן את הקוד ואראה שכל "מלבן" סרטון הוא בעצם li בעל מאפיין קלאס כלשהו –



ונראה שהדרך לרכיב שנרצה לקחת, רכיב שם הסרטון, עוברת כך –



נשתמש בידיעת מבנה זה על מנת למצוא את הרכיבים בדרך קצת אחרת, כך שבמידה וdiv מכיל a נוכל לגשת אל a כך a_var = div_var.a_var בצורה זו, יוחזר ערך הa הראשון שהרכיב מכיל. בדומה לפונקציית הfind. כעת נשלים את הקוד בהתבסס על הקונספט הזה ועל קונספט הfind_all -

from bs4 import BeautifulSoup
import requests
____
source = requests.get('https://www.youtube.com/feed/trending').text
soup = BeautifulSoup(source,'lxml')
div,title,channel = None,None,None
for container in soup.find_all('li' , class_="expanded-shelf-content-item-wrapper"):
div = container.div.div.div.find_all('div')
____div = div[2]
____title = div.h3.a
____channel = div.div.a
____print(title.text)
____print(channel.text)

והפעולה תדפיס לנו את מה שתכננו.






אין תגובות:

הוסף רשומת תגובה