標籤:
PythonChallenge_3
一、實驗說明
1. 環境登入
無需密碼自動登入,系統使用者名稱shiyanlou,密碼shiyanlou
2. 環境介紹
本實驗環境採用帶案頭的Ubuntu Linux環境,實驗中會用到案頭上的程式:
1. LX終端(LXTerminal): Linux命令列終端,開啟後會進入Bash環境,可以使用Linux命令
2. Firefox:瀏覽器,可以用在需要前端介面的課程裡,只需要開啟環境裡寫的HTML/JS頁面即可
3. GVim:非常好用的編輯器,最簡單的用法可以參考課程[Vim編輯器]
3. 環境使用
使用GVim編輯器輸入實驗所需的代碼及檔案,使用LX終端(LXTerminal)運行所需命令進行操作。
完成實驗後可以點擊案頭上方的“實驗”儲存並分享實驗結果到微博,向好友展示自己的學習進度。實驗樓提供後台系統,可以真實有效證明您已經完成了實驗。
實驗記錄頁面可以在“我的首頁”中查看,其中含有每次實驗的及筆記,以及每次實驗的有效學習時間(指的是在實驗案頭內操作的時間,如果沒有操作,系統會記錄為發獃時間)。這些都是您學習的真實性證明。
二、課程介紹
本次`PythonChallenge`系列一共有11個項目,持續更新中~~~,每個項目課程裡面會詳細講解3個`pythonchallenge`通關題目以及不同解決方案,課後習題裡面布置一個任務題,該題目會在下一個項目中被揭開面紗。
本系列題目屬於線上闖關題,由於實驗樓暫時不提供訪問外網,因此請各位驗證答案的時候煩勞點擊自己的瀏覽器訪問網頁以驗證答案。
所有題目和參考的解決方案著作權歸[PythonChallenge官網],課程編寫屬於實驗樓原創,歡迎在問答區積極提問,小編會積極解答,也歡迎在評論區吐槽~
三、實驗回顧
在上一個[項目課]中,我們學到了很多知識,比如:`re`模組中的一些函數,`urllib`模組的使用以及函數`reduce`。記性不算太差的你們估計還記得在上一次的課程中小編有留給大家一個課後作業,不知道你們完成的怎樣呢?
不管是否得到答案,讓小編帶著你一起解決這個問題吧!
四、作業題解析
### 問題:請訪問[挑戰題連結]查看原始碼,找到通往下一個網址的連結。(提示:與`zip`有關)
**小編腦洞:**
首先查看原始碼:
經過這幾次題目的摸索,我們知道一般答案都是隱藏在注釋裡面的(`<!-- -->`的內容)。首先第一個注釋是單詞`zip`,第二個注釋稍微比較長,大致的意思是:下面的內容與謎語本身無關,只希望大家能夠給`pythonchallenge`這個項目提供一點資助。那麼,第二個注釋就沒有什麼作用。再看第一個注釋,只有一個單詞`zip`,那麼答案就是`zip`了,因此修改連結為:[http://www.pythonchallenge.com/pc/def/zip.html]。得到這樣的結果:
意思是:找到了`zip`,那麼`zip`應該就隱藏在原始碼中:
源碼中並沒有給予什麼資訊,那麼是不是`zip`指的是`zip`壓縮包呢?再次返回修改原連結,將`html`換成`zip`,結果真是一個壓縮包,關於這個壓縮包,已經上傳至實驗樓環境,因此輸入以下命令下載檔案並查看壓縮包內容:
1 $ wget http://labfile.oss.aliyuncs.com/courses/411/channel.zip2 $ unzip -l channel.zip
檔案內容如下:
一共有910個檔案,大多數檔案的命名都是數字型,解壓並查看說明文檔`readme.txt`:
1 $ unzip channel.zip 2 $ vi readme.txt
根據上面的提示,我們瞭解到兩個資訊:
- 迴圈是從`90052.txt`這個檔案開始;
- 答案就隱藏在zip壓縮包檔案夾的內容中。
查看`90052.txt`這個文檔內容如下:
看到這句話的時候,你是不是覺得似曾相識?是的,在上一個挑戰項目中也出現過這麼一句話,區別在於上一次的題目是使用`urllib`模組在網頁上尋找關鍵字,這一次是在壓縮包內尋找答案。
演算法如下:
- 1. 設定初識起點,進入迴圈,使用Regex匹配檔案內容中的數字;
- 2. 將檔案內容中的數字作為下一個被開啟的檔案名稱;
- 3. 迴圈條件是找到不是以數字結尾的檔案並列印結果
1 import re 2 3 findnothing = re.compile(r‘Next nothing is (\d+)‘).match 4 5 while True: 6 fname = seed + ‘txt‘ 7 text = open(fname, ‘r‘).read() 8 m = findnothing(text) 9 if m:10 seed = m.group(1)11 else:12 print text13 break
列印結果如下:
意思是讓我們收集注釋。
關於注釋,每一個檔案都有它的描述資訊,可以通過輸入命令查看壓縮包內的檔案的描述資訊:
1 unzip -l channel.zip
給出每個檔案的四個資訊,比如`reame.txt`檔案,它的注釋資訊就是`*`,該檔案的大小為`84`位元組,該檔案的最後修改時間是`2005-04-28`,檔案名稱為`readme.txt`。將這些注釋資訊串連起來就可以看看結果能不能告訴我們資訊。
`Python`中有一個關於收集壓縮包資訊的模組`zipfile`,該模組的詳細說明文檔見[官方文檔](https://docs.python.org/2/library/zipfile.html)。
該模組中有一個類需要我們瞭解——`zipfile.ZipFile`。該模組主要用於讀寫`zip`類型的檔案。該類裡面有一個函數`getinfo(name)`用於返回壓縮檔中命名為`name`的檔案資訊,由於本次樣本裡面需要用到檔案資訊裡面的解釋部分,因此直接調用`zipfile.ZipFile.getinfo(name).comment`就可以返回`name`檔案的注釋。
因此修改代碼如下:
1 import zipfile, re 2 3 findnothing = re.compile(r"Next nothing is (\d+)").match 4 comments = [] # 收集注釋資訊的列表 5 z = zipfile.ZipFile("channel.zip", "r") # 讀取壓縮包檔案 6 seed = "90052" 7 8 while True: 9 fname = seed + ".txt"10 comments.append(z.getinfo(fname).comment)11 guts = z.read(fname)12 m = findnothing(guts)13 if m:14 seed = m.group(1)15 else:16 break17 print "".join(comments) # 列印所有注釋資訊
那麼答案應該就是`hockey`了,轉到該連結:
然後提示讓我們看一下字母,並且提示該單詞指的是存在於空氣中。上面組成`HOCKEY`的圖中恰好是由字母`O C Y G E N`組成,也就是單詞空氣——`oxygen`。
因此來到[下一題]。
五、第七個挑戰題
問題:根據這副圖片找到通往下一個連結的單詞。
**小編腦洞:**
然而這一次原始碼中並沒有提供額外的資訊,那麼只能看圖,仔細觀察,發現這個圖並不完整,圖的中間被一條不同深度的灰階長條給掩蓋,那麼資訊很可能就隱藏在這裡面。那麼影像處理中我們知道每一個圖片都是由無數個像素值組成,實際上就是一個[像素]構成的矩陣,那麼答案很可能與這些像素值有關。關於這個問題的具體思路,有興趣的朋友可以看一下我的[部落格]。
首先下載用於處理映像的`Image`模組,然後下載本題所需要處理到的圖片`oxygen.png`。
1 $ sudo apt-get install python-imaging2 $ wget http://labfile.oss.aliyuncs.com/courses/411/oxygen.png
輸入以下代碼觀察圖片的大小:
1 import Image2 img = Image.open(‘oxygen.png‘) 3 img.size
由`img.size`的返回結果可知,該圖片的水平方向和垂直方向上每英寸長度上的像素分別為`629`和`95`;利用畫圖工具可將這段馬賽克地區的座標提取出來:
橫座標的範圍是:`0-609`,縱座標的範圍是:`43-53`。
然後利用`Image`模組裡面的函數`getpixel`獲得這一地區的像素資料:
1 # 列表運算式2 data = [img.getpixel((i, j)) for i in range(0, 609) for j in range(43, 53)]3 print data
觀察列印的結果,你會發現輸出的像素列表是一個`4`元組,其中元組的前三個元素分別對應相應的`RGB`分量:`r`、`g`、`b`,並且由於灰色滿足條件是`r=g=b`,且觀察到元組每重複7次變化一次,那麼如何將這些輸出結果與答案聯絡?
一般情況下,答案的連結都是英文字母,那麼可以嘗試把這些數值轉化為經過函數`chr`將這些`ASCII碼`轉換為相應的英文字母。
1 # 先選取印第45行的所有像素資訊2 row = [chr(img.getpixel((i, 43))[0]) for i in range(0, 609, 7)]3 "".join(row)
給的那句話的意思是下一關的答案是`[105,110,116,101,103,114,,105,116,121]`。好說,將這些`ASCII碼`轉為字母,並串連成字串:
通往下一關的單詞是`integrity`,因此轉到下一關[連結]。
七、第八個挑戰題
問題:找到消失的連結
**小編腦洞:**
找到消失的連結?那麼通關口應該不是簡單的單詞替換而是一個超連結,看看原始碼是否有我們需要的資訊:
我們注意到在`center/img`中有一個屬性`usemap`為`notisect`,關於`notisect`的描述在`\map\area`下面有描述,也就是說這是`interity`這個圖裡面的連結,關於`coords`的內容是圖片的某一地區,該地區指向一個連結`@href=‘../return/good/html‘`點擊圖片彈出如下對話方塊(更多關於`img`標籤的`usemap`屬性介紹請查看[文檔]):
也就是說我們需要在原網頁中找到使用者名稱和密碼才能登陸該身分識別驗證。
再次觀察原始碼中的注釋部分,發現:
如果把`un`(username)後面的字串解釋為使用者名稱,那麼`pw`(password)裡面的字串就是密碼。
那麼這些字串應該如何解碼呢?仔細觀察字串的組成形式,無論是使用者名稱還是密碼都是`BZ`開頭的字串,後來瞭解到`BZ`開始的字串實際上是被`bz2`壓縮後的一種格式,那麼如何解壓呢?首先匯入該模組,然後輸入`dir(bz2)`查看`bz2`模組的函數:
`compress`是`壓縮`函數,那麼`decompress`就是解壓函數,繼續查看函數用法:
由於我們的字串比較少,因此可以使用函數`decompress(data)`解壓資料:
1 import bz22 un = ‘‘BZh91AY&SYA\xaf\x82\r\x00\x00\x01\x01\x80\x02\xc0\x02\x00 \x00!\x9ah3M\x07<]\xc9\x14\xe1BA\x06\xbe\x084‘3 pw = ‘BZh91AY&SY\x94$|\x0e\x00\x00\x00\x81\x00\x03$ \x00!\x9ah3M\x13<]\xc9\x14\xe1BBP\x91\xf08‘4 bz2.decompress(un)5 bz2.decompress(pw)
得到使用者名稱為`huge`,密碼為`file`,其實這個問題很簡單,只要瞭解到`BZ`這種格式的字串是一種壓縮形式,然後進行相應的解壓就可以解決問題。
八、任務
問題:請把點串連起來,[題目連結](提示:原始碼,原始碼!)。
pythonchallenge(三)