5 דקות על Web Scraping

19/05/2016

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

1. מה הרעיון

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

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

2. דוגמת קוד: חדשות אתר רוטר

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

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

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

תחילה הקוד ולאחריו ההסבר:

require 'open-uri'
require 'nokogiri'

doc = Nokogiri::HTML(open("http://rotter.net/"))

news = doc.css('a[target=news] span')

news.each_with_index do |item, index|
  puts "[#{index}] #{item.text}"
end

3. איך זה עובד

החוכמה כולה נמצאת בקריאה לפונקציה doc.css: הפונקציה מקבלת CSS Selector ומחזירה את כל האלמנטים מתוך ה HTML שמתאימים ל Selector. במקרה של רוטר, כל אלמנט שמיצג פריט חדשותי הינו אלמנט <a> הכולל מאפיין target שערכו news. בגלל חוקיות זו של האתר קל להגיע ל CSS שישלוף את כל פריטי החדשות. כמובן, ככל שהאתר מורכב יותר או לחלופין פריטי התוכן שמעניינים אתכם קבורים במקומות שיותר קשה להגיע אליהם, כך הקוד יצא יותר מסורבל.

אם אתם מתעצלים להתקין רובי או את הספריה Nokogiri הכנתי מכונה וירטואלית שכבר כוללת את כל מה שצריך ואת הסקריפט. פשוט להוסיף מים ולהריץ עם: ruby rotter.rb: