pythonchallenge 一個超有意思的 Python 綜合能力測試網站

最近在網上看到一個非常有意思的 Ptyhon 遊戲通過網站叫:pythonchallenge,一共有 33 關,每一關都需要利用 Python 知識解題找到答案,然後進入下一關。很考驗對 Python 綜合掌握能力,比如有的闖關需要用到正則表達式,有的要用到簡單的爬蟲。

[圖片上傳失敗...(image-679c84-1558091688835)]

平常學 Python 都是按章節順序、包或者模塊在學習,容易前學後望。正好可以拿這個網站來綜合測試一下對 Python 的掌握情況,以便查缺補漏。

來說說這個網站怎麼玩。

[圖片上傳失敗...(image-f27161-1558091688835)]

這是網站主頁面,很有歷史感對吧,誕生了已有十幾年了。但千萬不要因爲看着像老古董而小瞧它。

我們來玩玩看,點擊「get challenged」開始挑戰。

第 0 關是 Warming up 熱身環節:

這一關要求是修改 URL 鏈接,給的提示是電腦上的數學表達式: 2 的 38 次方,所以大概就是需要計算出數值,然後修改url 進入下一關。

所以這關就是考Python 的基本數值運算,你知道怎麼算麼?

隨意打開個 IDE,比如 Python 自帶終端,只要一行代碼就能計算出結果:

[圖片上傳失敗...(image-43dbd0-1558091688837)]

把原鏈接中的 0替換爲 274877906944回車就會進入下一關:

[圖片上傳失敗...(image-1dbcd5-1558091688837)]

遊戲這就正式開始了。圖片中的筆記本給了三組字母,很容易發現規律:前面的字母往後移動兩位就是後面的字母。

那麼需要做的就是根據這個規律把下面的提示字符串,做位移解密得到真正的句子含義:

這道題考察字符串編碼和 for 循環相關知識,代碼實現如下:

text = '''g fmnc wms bgblr rpylqjyrc gr zw fylb. rfyrq ufyr amknsrcpq
    ypc dmp. bmgle gr gl zw fylb gq glcddgagclr ylb rfyr'q
    ufw rfgq rcvr gq qm jmle. sqgle qrpgle.kyicrpylq()
    gq pcamkkclbcb. lmu ynnjw ml rfc spj.'''

text_translate = ''
for i in text:
    if str.isalpha(i):
        n = ord(i)
        if i >= 'y':
            n = ord(i) + 2 - 26
        else:
            n = ord(i) + 2
        text_translate += chr(n)
    else:
        text_translate += i
print(text_translate)

得到結果:

i hope you didnt translate it by hand. 
thats what computers are for. 
doing it in by hand is inefficient and that's why this text is so long. 
using string.maketrans()is recommended. now apply on the url.

作者很風趣,當然不能手動去一個推算了,推薦用 string.maketrans() 這個方法解決,我們上面採取的是比較直接的方法,官方給出了更爲精簡的方法:

import string
l = string.lowercase
t = string.maketrans(l, l[2:] + l[:2])
print (text.translate(t))

然後把 url 中的 map 改爲ocr回車就來到了第 2 關:

[圖片上傳失敗...(image-696ac2-1558091688837)]

作者接着說過關的提示可能在書裏(當然不可能了)也可能在網頁源代碼裏。那就右鍵查看源代碼往下拉看到綠色區域,果然找到了問題:

[圖片上傳失敗...(image-c53cde-1558091688837)]

意思就是:要在下面這一大串字符裏找到出現次數最少的幾個字符

考察了這麼幾個知識點:

  • 正則表達式提取字符串
  • list 計數
  • 條件語句

如果是你,你會怎麼做?

來看下,十行代碼怎麼實現的:

import requests
url = 'http://www.pythonchallenge.com/pc/def/ocr.html'
res = requests.get(url).text
text = re.findall('.*?<!--.*-->.*<!--(.*)-->',res,re.S)
# list轉爲str便於遍歷字符
str = ''.join(text)

lst = []
key=[]
#遍歷字符
for i in str:
    #將字符存到list中
    lst.append(i)
    #如果字符是唯一的,則添加進key
    if i not in key:
        key.append(i)
# 將list列表中的字符出現字數統計出來
for items in key:
    print(items,lst.count(items))

首先,用 Requests 請求網頁然後用正則提取出字符串,接着 for 循環計算每個字符出現的次數。

% 6104
$ 6046
@ 6157
_ 6112
^ 6030
# 6115
) 6186
& 6043
! 6079
+ 6066
] 6152
* 6034
} 6105
[ 6108
( 6154
{ 6046

e 1
q 1
u 1
a 1
l 1
i 1
t 1
y 1

可以看到出現次數最少的就是最後幾個字符,合起來是「equality」,替換 url 字符就闖過過了第 2 關進入下一關繼續挑戰。是不是有點意思?

後面每一關都需要用到相關的 Python 技巧解決,比如第 4 關:

[圖片上傳失敗...(image-f920e6-1558091688837)]

這一關作者弄了個小惡作劇,需要手動輸入數值到 url 中然後回車,你以爲這樣就完了麼?並沒有它有會不斷重複彈出新的數值讓你輸入,貌似沒完沒了。

到這兒就能發現肯定不能靠手動去完成,要用到 Python 實現自動填充修改 url 回車跳轉到新 url,循環直到網頁再也無法跳轉爲止。

如果是你,你會怎麼做?

其實一段簡單的爬蟲加正則就能搞定。思路很簡單,把每次網頁中的數值提取出來替換成新的 url 再請求網頁,循環下去,代碼實現如下:

import requests
import re
import os

# 首頁url
resp = requests.get(
    'http://www.pythonchallenge.com/pc/def/linkedlist.php?nothing=12345').text
url = 'http://www.pythonchallenge.com/pc/def/linkedlist.php?nothing='
# 計數器
count = 0
while True:
    try:
        # 提取下一頁動態數值
        nextid = re.search('\d+', resp).group()
        count = count + 1
        nextid = int(nextid)
    except:
        print('最後一個url爲:%s' % nexturl)
        break

    # 獲取下一頁url
    nexturl = url + str(nextid)
    print('url %s:%s' % (count, nexturl))
    # 重複請求
    resp = requests.get(nexturl).text

輸出結果如下:

gif

可以看到,最終循環了 85 次找到了最後一個數字16044,輸入到 url 中就闖關成功。

33 關既有趣又能鍛鍊使用 Python 解決問題的技巧,感興趣的話去玩玩看。

網址:http://www.pythonchallenge.com/

如果遇到不會做的題,可以在這裏找到參考答案:

中參考文教程:

https://www.cnblogs.com/jimnox/archive/2009/12/08/tips-to-python-challenge.html

官方參考教程:

http://garethrees.org/2007/05/07/python-challenge/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章