הבלוג של ינון פרק

טיפים קצרים וחדשות למתכנתים

איך לא לעבוד עם קאפצ'ה

13/02/2019

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

אז איך קאפצ'ה בכלל עובדת? ואיך היא יכולה להישבר? טוב ששאלתם.

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

רואים כבר איפה זה יכול להישבר?

הבעיה המרכזית בהטמעת מנגנון כזה היא מה קורה כשהשרת שלכם מנסה לבדוק מול ספק הקאפצ'ה שלו האם קאפצ'ה היא וולידית בפעם השניה. או במילים אחרות מי אחראי על "למחוק" את הקאפצ'ה אחרי ששלחתם אותה וקיבלתם את המידע פעם אחת. מצד אחד אולי אין לנו יותר מדי תמונות במאגר ונשמח לשלוח את אותה קאפצ'ה לכמה משתמשים (או אפילו לאותו משתמש כמה פעמים), אבל מצד שני משתמש שמכיר את הצמד "מזהה קאפצ'ה <-> האותיות" יכול להשתמש בזה כדי לשלוח בקשות אוטומטיות לשרת.

הנה התרחיש הבעייתי:

  1. משתמש פותר את הקאפצ'ה ורושם אצלו את כל הפרטים בטופס שנשלחים לשרת, כולל את מזהה הקאפצ'ה והפיתרון שלה.

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

  3. השרת שולח לספק הקאפצ'ה שלו את מזהה הקאפצ'ה והפיתרון ומקבל תשובה שהכל תקין וזה אכן פיתרון טוב לקאפצ'ה.

והנה קיבלנו מידע חדש בלי לפתור את הקאפצ'ה פעם שניה.

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

מאפס לאחד

12/02/2019

מה יותר קשה - למצוא את העבודה הראשונה בהייטק או להתקדם לעבודה השניה? למצוא את הלקוח הראשון בתור עצמאי או להתקדם ללקוח החמישי? לבנות את המשחק הראשון ב App Store או הרביעי?

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

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

והלקוח הראשון? הוא כנראה חבר-של-חבר שרק מחכה שתהפכו לעצמאים כדי שיוכל לקנות מכם.

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

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

המילים שנוני מוזס הכי אוהב

11/02/2019

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

שימוש אחר של Web Scraping, עליו ארצה לדבר היום, הוא היכולת להסתכל במכה אחת על המון מידע ברשת ולהגיע למסקנות שבצורה ידנית היה קשה מאוד להגיע אליהן. בתחום של Machine Learning אתם תפגשו אנשים שלוקחים את המידע מהרשת ונותנים למחשב להבין מתוך מידע זה מה הולך לקרות מחר. וגם בלי Machine Learning אפשר לעשות דברים מעניינים עם מידע כשמסתכלים עליו אחרת ממה שמי שכתב אותו התכוון.

כך בשביל למצוא את המילים שנוני מוזס הכי אוהב אפשר להסתכל בכל המבזקים ב ynet ולספור כמה פעמים מופיעה כל מילה במבזקים.

כשאנחנו רוצים לקחת את כל המילים באתר בכל הדפים שלו עדיף לשלוח מספר בקשות במקביל (באזור ה 8-10 במקביל נותן תוצאה טובה). 8 בקשות במקביל עובר מתחת לרדאר של רוב האתרים, בוודאי הגדולים. לפני כמה ימים פרסמתי כאן דוגמת קוד שמביאה את כל המבזקים מ ynet:

import requests
from bs4 import BeautifulSoup

url = 'https://www.ynet.co.il/home/0,7340,L-184,00.html'
r = requests.get(url)
soup = BeautifulSoup(r.text)
for link in soup.select('a.smallheader'):
    print(link.text)

עכשיו אנחנו רוצים להמשיך את התוכנית הזאת צעד נוסף - עבור כל מבזק נרצה לקחת הכתבה עצמה ולספור את המילים שבה. בשביל לפתוח מספר בקשות רשת במקביל אני משתמש בספריה שנקראת requests_futures. הספריה מאוד פשוטה ועובדת בממשק שנראה כמו requests, רק שהיא שולחת את הבקשות במקביל ומאפשרת לכם להוסיף קוד טיפול בכל תשובה.

בהנחה שיש לכם רשימה של URL-ים תוכלו להשתמש בקוד שנראה בערך כך כדי להביא את כולם מהרשת במקביל ולראות את סטטוס התשובה של כל אחד:

q = [session.get(url) for url in urls]
results = [f.result() for f in q]

ובתוך תוכנית מלאה הסיפור נראה כך:

import requests
from bs4 import BeautifulSoup
from requests_futures.sessions import FuturesSession
import collections

url = 'https://www.ynet.co.il/home/0,7340,L-184,00.html'
r = requests.get(url)
soup = BeautifulSoup(r.text, 'html5lib')

urls = [f'https://www.ynet.co.il{item.get("href")}' for item in soup.select('a.smallheader')]

word_counter = collections.Counter()

def parse_ynet_article(resp, *args, **kwargs):
    page = BeautifulSoup(resp.text, 'html5lib')
    text = page.select('.art_body span')[0].text
    word_counter.update(text.split())

session = FuturesSession()
session.hooks['response'] = parse_ynet_article

q = [session.get(url) for url in urls]
results = [f.result() for f in q]
print(word_counter)

הפונקציה parse_ynet_article תקרא באופן אוטומטי בכל פעם שהסקריפט סיים להוריד כתבה מ ynet. היא מפענחת את ה HTML, סופרת את המילים בתוכן הכתבה ומוסיפה אותן ל Counter. כל זה קורה מ-8 תהליכונים במקביל ומנוהל באופן אוטומטי על ידי requests_futures. בצורה דומה יכולתם לשמור את כל ה HTML-ים של האתר אליכם או לעשות כל עיבוד אחר על התוכן.

איך יודעים אם כדאי לקחת פרויקט?

10/02/2019

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

  1. עד כמה הפרויקט הזה יכול לעזור ללקוח?

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

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

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

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

תוכנית לימודים

09/02/2019

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

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

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

רוצים לבנות לעצמכם תוכנית לימודים (לא משנה למה)? תתחילו עם המחגר. כשהגלגל זז רק קדימה ההצלחה מובטחת.

הדלס מי?

08/02/2019

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

בואו נצא לסיבוב עם כרום נטול הראש כדי לראות איך הוא מתמודד עם העולם.

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

$ pip install selenium

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

http://chromedriver.chromium.org/downloads

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

import os
from selenium import webdriver
from selenium.webdriver.chrome.options import Options

CHROMEDRIVER_PATH = '/Users/ynonperek/bin/chromedriver'

options = Options()
options.headless = True
driver = webdriver.Chrome(CHROMEDRIVER_PATH, chrome_options=options)

# Start Here
driver.get("https://www.ynet.co.il/home/0,7340,L-184,00.html")
news = driver.find_elements_by_css_selector('a.smallheader')
for item in news:
    print(item.text)

driver.close()

החלק הראשון שמופיע לפני ה Start Here הוא הגדרת הכלים. אנחנו צריכים להגיד לסלניום איפה הוא יכול למצוא את הדרייבר שהורדנו ושאנחנו רוצים לרוץ ללא ראש. מכאן ממשיכים כמו בתוכנית סלניום רגילה רק במקום לבדוק שדברים נמצאים במקום אנחנו משתמשים בהם כדי להדפיס את המידע.

באותו האופן נוכל להדפיס את הכותרות מאתר רוטר:

import os  
from selenium import webdriver  
from selenium.webdriver.chrome.options import Options  

CHROMEDRIVER_PATH = '/Users/ynonperek/bin/chromedriver'

options = Options()
options.headless = True
driver = webdriver.Chrome(CHROMEDRIVER_PATH, chrome_options=options)

# Start Here
driver.get("http://rotter.net/")
news = driver.find_elements_by_css_selector('a[target="news"] span')
for item in news:
    print(item.text)

driver.close()

בגלל שמדובר בסלניום אנחנו יכולים לבצע פעולות באתרים ממש כאילו היינו גולשים בהם מדפדפן כרום אמיתי, כולל כל היכולות של מילוי מידע בטפסים, לחיצה על כפתורים והרצת קוד JavaScript. הבעיה היחידה עם כל הטוב הזה היא שיש לנו את דפדפן כרום שצריך לדאוג לו. הפעלת הדפדפן עם הפעלת התוכנית, ניווט לדפים אחרים וסגירתו בסוף התוכנית משפיעים על הביצועים ומייצרים קוד שרץ יותר לאט. כמה יותר לאט? על המחשב שלי הצגת הכותרות מ ynet לקחה לי 5 שניות בגירסת הסלניום לעומת חצי שניה בגירסת ה Beautiful Soup. בתוכניות יותר גדולות תוספת הזמן להמראה עשויה להיות פחות משמעותית כי אנחנו מבלים יותר זמן בשיטוטים באתר.

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

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

https://www.tocode.co.il/workshops/64

בואו נדפיס את כל הכותרות מרוטר נט לשורת הפקודה

07/02/2019

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

צפיה בקוד של אתר רוטר יכולה לרמוז לנו מה הבעיה:

<!--</u>531268</u><--></u><span style='font-size:9.0pt;color:red'><b>16:29</b></span>&nbsp; <a target='news' HREF='http://rotter.net/forum/scoops1/531268.shtml'><span style='font-size:10.0pt;color:000099'></g>אחרי הספירה גדעון סער מקום רביעי</g></span></a><br>

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

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

import requests
from bs4 import BeautifulSoup
from lxml.html.soupparser import fromstring
from lxml import etree

url = 'http://rotter.net/'
r = requests.get(url)
r.encoding = 'iso8859-8'
root = fromstring(r.text)
headlines = [
        text for text in root.xpath('//a[@target="news"]/../text()')
        if text != '\n' and text != '\n\n' and text != '\xa0 '
]

for text in headlines:
    print(text)

בניגוד ל ynet, ברוטר ה Character Encoding לא מוגדר טוב ולכן צריך להגיד ל requests בצורה מפורשת שאנחנו רוצים עברית. פקודת ה xpath למציאת הטקסטים היתה:

root.xpath('//a[@target="news"]/../text()')

זה מאוד מזכיר CSS Selector מלבד סימן הנקודה-נקודה שמציין מעבר לאלמנט ההורה. בעברית זה יישמע משהו כמו - קח כל אלמנט a שיש לו מאפיין target עם ערך news, תמצא את ההורה של כל אחד מהם, ומההורה הזה קח את כל הטקסטים שנמצאים ישירות תחתיו. אלה בדיוק הטקסטים שיימצאו "ליד" אלמנטי ה a, בגלל שה g גרם להם לצאת מה a.

מעניין לציין שלדפדפנים אין את הבעיה הזאת ובתוך ה Developer Console של כרום אנחנו יכולים בכיף לכתוב:

$$('a[target="news"]')[0].textContent

כדי לקבל את הטקסט של האייטם הראשון.

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

https://www.tocode.co.il/workshops/64

קצת מכל דבר

06/02/2019

הדרך הכי טובה ללמוד היא קצת מכל דבר-

גם לכתוב משהו לבד בטכנולוגיה החדשה, גם לקרוא את התיעוד, גם להיתקע ולחפש תשובות ב Stack Overflow, גם ללכת למיטאפ כדי להכיר אנשים שעובדים בזה, גם להיכנס לקבוצת פייסבוק שלהם, גם להיכנס לערוץ IRC של הפרויקט, גם לראות הרצאות מכנסים ב Youtube, גם להעביר הרצאה במיטאפ ההוא שהתחלתם ללכת, גם לקרוא ספר מקצועי.

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

אפשר מחר

05/02/2019

חלק מהמשימות שלכם הולכות להיות יותר קשות עם הזמן, וחלק יותר קלות.

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

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

מצד שני שינויים טכנולוגיים לרוב מחלקים דיבידנדים דווקא למי שמחכה. ריאקט ראוטר היה ממש גרוע בגירסאות הראשונות שלו, ומי שחיכה לגירסא 4 קיבל מערכת בשלה ויציבה. בצורה דומה React Native עשתה חיים ממש קלים למפתחי Mobile בהשוואה ל PhoneGap, וכמובן שהחיים ב JavaScript הרבה יותר קלים אחרי ES8.

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

בואו נציג את כל הכותרות מ ynet דרך שורת הפקודה

04/02/2019

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

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

שני דברים שכדאי לשים לב אליהם עוד לפני שניגשים לכתוב את שורת הקוד הראשונה:

  1. הכי קל לקבל את הכותרות בדף ה"מבזקים" של ynet. אם תצליחו למצוא את הכפתור "מבזקים" תוכלו להעתיק את ה url משם.

  2. בדף המבזקים כל כותרת היא תגית a עם קלאס בשם smallheader.

אז מה עושים? לוקחים את ה HTML מדף המבזקים, זורקים אותו ל HTML Parser ושם שולפים את כל אלמנטי ה a עם הקלאס smallheader. בפייתון הספריה שעוזרת לקבל קובץ HTML לפי כתובת ברשת נקראת requests והספריה שמפענחת קבצי HTML נקראת Beautiful Soup. כשמחברים את שתיהן יחד מקבלים:

import requests
from bs4 import BeautifulSoup

url = 'https://www.ynet.co.il/home/0,7340,L-184,00.html'
r = requests.get(url)
soup = BeautifulSoup(r.text)
for link in soup.select('a.smallheader'):
    print(link.text)

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