תרגיל Python ל-Log Puzzle

בתרגיל Log Puzzle, עליכם להשתמש בקוד Python כדי לפתור שתי חידות. בתרגיל הזה אנחנו משתמשים במודול urllib, כפי שמוצג בקטע כלי עזר של Python. הקבצים לתרגיל הזה נמצאים ב-logpuzzle בתוך google-python-exercises (מורידים את google-python-exercises.zip אם עדיין לא עשיתם זאת), לפרטים נוספים, ראו הגדרה). מוסיפים את הקוד אלlogpuzzle.py. חדש.

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

כתובות ה-URL של הפרוסות מוסתרות בתוך קובצי יומן של Apache (שרת האינטרנט apache בקוד פתוח הוא השרת הנפוץ ביותר בשימוש באינטרנט). כל קובץ יומן הוא משרת מסוים, וכתובות ה-URL הרצויות של הפרוסות מוסתרות בתוך היומנים. קובץ היומן מקודד באופן הבא מאיזה שרת הוא מגיע: קובץ היומן animal_code.google.com מגיע מהשרת code.google.com (נניח באופן רשמי ששם השרת הוא מה שמופיע אחרי הסרגל התחתון הראשון). קובץ היומן animal_code.google.com מכיל את הנתונים עבור ה-'animal' תמונה של חשיבה. למרות שלנתונים בקובצי היומן יש תחביר של שרת אינטרנט אמיתי של Apache, הנתונים שמעבר לנתונים שדרושים לחידה הם נתונים אקראיים מקובץ יומן אמיתי.

כך נראית שורה אחת מקובץ היומן (כך נראים קובצי יומן של Apache):

10.254.254.28 - - [06/Aug/2007:00:14:08 -0700] "GET /foo/talks/ HTTP/1.1"
200 5910 "-" "Mozilla/5.0 (X11; U; Linux i686 (x86_64); en-US; rv:1.8.1.4) Gecko/20070515 Firefox/2.0.0.4"

המספרים הראשונים הם הכתובת של הדפדפן ששולח את הבקשה. החלק המעניין ביותר הוא "GET path HTTP" שמראה את הנתיב של בקשת אינטרנט שהתקבלה בשרת. הנתיב עצמו אף פעם לא מכיל רווחים, והוא מופרד מ-GET ו-HTTP באמצעות רווחים (הצעה לביטוי רגולרי: \S (באותיות רישיות S) תואם לכל תו שהוא לא רווח). חפשו ביומן את השורות שבהן מופיעה המחרוזת 'חשיבה' מופיע בתוך הנתיב, תוך התעלמות מהשורות הרבות האחרות ביומן.

חלק א' – קובץ יומן עם כתובות URL

משלימים את הפונקציה read_urls(filename) שמחלצת את כתובות ה-URL של הפאזל מתוך קובץ יומן. חיפוש כל "החידות" בכתובות ה-URL של הנתיבים בקובץ היומן. צריך לשלב את הנתיב מכל כתובת URL עם שם השרת משם הקובץ כדי ליצור כתובת URL מלאה, למשל: "http://www.example.com/path/puzzle/from/inside/file". מסננים כתובות URL שמופיעות יותר מפעם אחת. הפונקציה read_urls() צריכה להחזיר את הרשימה של כתובות ה-URL המלאות, שממוינות לפי סדר אלפביתי וללא כפילויות. אם תשתמשו בכתובות ה-URL בסדר אלפביתי, הפרוסות של התמונה יופיעו בסדר הנכון משמאל לימין כדי ליצור מחדש את התמונה המקורית של בעל החיים. במקרה הפשוט ביותר, Main() צריכה פשוט להדפיס את כתובות האתר, אחת בכל שורה.

$ ./logpuzzle.py animal_code.google.com
http://code.google.com/something/puzzle-animal-baaa.jpg
http://code.google.com/something/puzzle-animal-baab.jpg
...

חלק ב' – הורדת חשיבה לתמונות

משלימים את הפונקציה download_images() שמקבלת רשימה ממוינת של כתובות URL וספרייה. מורידים את התמונה מכל כתובת URL לספרייה הנתונה, ויוצרים קודם את הספרייה לפי הצורך (כדי ליצור ספרייה אפשר לעיין במודול os כדי ליצור ספרייה ובמודול urllib.urlretrieve() להורדת כתובת URL). נותנים שמות לקובצי התמונות המקומיים באמצעות סכמה פשוטה כמו 'img0', 'img1', 'img2' וכן הלאה. אולי כדאי להדפיס קצת "מאחזר..." את שורת הפלט של הסטטוס בזמן הורדת כל תמונה, מכיוון שהיא עלולה להיות איטית ונוחה שיש אינדיקציה מסוימת שהתוכנה פועלת. כל תמונה היא פרוסה אנכית קטנה מהמקור. איך לחבר את הפרוסות כדי ליצור מחדש את התמונה המקורית? אפשר לפתור אותה בצורה טובה עם קצת HTML (לא נדרש ידע ב-HTML).

הפונקציה download_images() אמורה ליצור גם קובץ index.html בספרייה עם תג *img* כדי להציג כל קובץ תמונה מקומי. תגי התמונה צריכים להיות באותה שורה יחד, ללא הפרדה. כך, הדפדפן מציג את כל הפרוסות יחד באופן חלק. אין צורך בידע ב-HTML כדי לעשות זאת. פשוט צרו קובץ index.html שנראה כך:

<html>
<body>
<img src="img0"><img src="img1"><img src="img2">...
</body>
</html>

כך היא אמורה להיראות כשמורידים את החידה:

$ ./logpuzzle.py --todir animaldir animal_code.google.com
$ ls animaldir
img0  img1  img2  img3  img4  img5  img6  img7  img8  img9  index.html

כשהכול עובד, פתיחת הקובץ index.html בדפדפן אמורה לחשוף את התמונה המקורית של בעל החיים. מהו בעל החיים בתמונה?

חלק ג' - ביטול ערבול של פרוסת תמונה

החידה השנייה כוללת תמונה של מקום מפורסם מאוד, אבל היא תלויה בסוג מיון מותאם אישית. בפאזל הראשון, אפשר למיין את כתובות ה-URL לפי סדר האלף-בית כדי שהתמונות יופיעו בסדר הנכון. במיון נעשה שימוש בכתובת ה-URL המלאה. עם זאת, נניח שאם כתובת ה-URL מסתיימת בתבנית ' -wordchars-wordchars.jpg', למשל: "http://example.com/foo/puzzle/bar-abab-baaa.jpg", אז כתובת ה-URL צריכה להיות מיוצגת על ידי המילה השנייה במיון (למשל baaa). לכן, מיון רשימה של כתובות URL שכל אחת מהן מסתיימת בתבנית word-word.jpg אמור לסדר אותן לפי המילה השנייה.

הרחב את הקוד כך שיסדרו כתובות URL כאלה בצורה נכונה, ואז אמורה להיות לך אפשרות לפענח את החידה השנייה מסוג places_code.google.com שמציגה מקום מפורסם. איזה מקום מוצג בה?

ייחוס CC: התמונות שבהן נעשה שימוש בפאזל הזה זמינות על ידי הבעלים שלהן במסגרת רישיון Creative Commons Attribution 2.5, שמעודד בנדיבות ליצור רמיקס מהתוכן הזה. תמונת החיה לקוחה מ-zappowbang של המשתמש ב-Flickr, ותמונת המקום היא מהיצירה הבוליאנית של המשתמש ב-Flickr.