我们平常学 Python 都是按章节顺序、包或者模块来学,容易前学后忘。也常有同学说,我已经看完了编程教室的入门教程,但不知道可以做点什么。那么正好可以拿这个网站来综合测试一下对 Python 的掌握情况,以便查缺补漏。
来说说这个网站怎么玩。
这是网站主页面,很有历史感对吧,诞生了已有十几年了。但千万不要因为看着像老古董而小瞧它。
我们来玩玩看,点击「get challenged」开始挑战。
第 0 关是 Warming up 热身环节:
这一关要求是修改 URL 链接,给的提示是电脑上的数学表达式:2 的 38 次方,所以大概就是需要计算出数值,然后修改 url 进入下一关。
所以这关就是考 Python 的基本数值运算,你知道怎么算么?
【提示】打开 Python 自带终端,一行代码就能计算出结果:
把原链接中的 0
替换为 274877906944
回车就会进入下一关:
游戏这就正式开始了。图片中的笔记本给了三组字母,很容易发现规律:前面的字母往后移动两位就是后面的字母。
那么需要做的就是根据这个规律把下面的提示字符串,做位移解密得到真正的句子含义:
这道题考察字符串编码和 for 循环相关知识,代码实现如下:
1 text = '''g fmnc wms bgblr rpylqjyrc gr zw fylb. rfyrq ufyr amknsrcpq 2 ypc dmp. bmgle gr gl zw fylb gq glcddgagclr ylb rfyr'q 3 ufw rfgq rcvr gq qm jmle. sqgle qrpgle.kyicrpylq() 4 gq pcamkkclbcb. lmu ynnjw ml rfc spj.''' 5 6 text_translate = '' 7 for i in text: 8 if str.isalpha(i): 9 n = ord(i)10 if i >= 'y' :11 n = ord(i) + 2 - 26 12 else :13 n = ord(i) + 2 14 text_translate += chr(n)15 else :16
text_translate += i17 print(text_translate)
得到结果:
1 i hope you didnt translate it by hand. 2 thats what computers are for. 3 doing it in by hand is inefficient and that's why this text is so long. 4 using string.maketrans()is recommended. now apply on the url.
作者很风趣:当然不能手动去一个推算了,推荐用 string.maketrans() 这个方法解决,我们上面采取的是比较直接的方法,官方给出了更为精简的方法:
1 import string2 l = string.lowercase3 t = string.maketrans(l, l[2 :] + l[:2 ])4 print (text.translate(t))
然后把 url 中的 map
改为ocr
回车就来到了第 2 关:
作者接着说过关的提示可能在书里(当然不可能了)也可能在网页源代码里。那就右键查看源代码往下拉看到绿色区域,果然找到了问题:
意思就是:要在下面这一大串字符里找到出现次数最少的几个字符
考察了这么几个知识点:
如果是你,你会怎么做?
【提示】来看下,十行代码快速实现:
1 import requests 2 url = 'http://www.pythonchallenge.com/pc/def/ocr.html' 3 res = requests.get(url).text 4 text = re.findall('.*?.*' ,res,re.S) 5 # list转为str便于遍历字符 6 str = '' .join(text) 7 8 lst = [] 9 key=[]10 #遍历字符 11 for i in str:12 #将字符存到list中 13 lst.append(i)14 #如果字符是唯一的,则添加进key 15 if i not in key:16 key.append(i)17 # 将list列表中的字符出现字数统计出来 18
for items in key:19 print(items,lst.count(items))
首先,用 Requests 请求网页然后用正则提取出字符串,接着 for 循环计算每个字符出现的次数。
1 % 6104 2 $ 6046 3 @ 6157 4 _ 6112 5 ^ 6030 6 # 6115 7 ) 6186 8 & 6043 9 ! 6079 10 + 6066 11 ] 6152 12 * 6034 13 } 6105 14 [ 6108 15 ( 6154 16 { 6046 17 18 e 1 19 q 1 20 u 1 21 a 1 22 l 1 23 i 1 24 t 1 25 y 1
可以看到出现次数最少的就是最后几个字符,合起来是「equality」,替换 url 字符就闯过过了第 2 关进入下一关继续挑战。是不是有点意思?
后面每一关都需要用到相关的 Python 技巧解决,比如第 4 关:
这一关作者弄了个小恶作剧,需要手动输入数值到 url 中然后回车,你以为这样就完了么?并没有它有会不断重复弹出新的数值让你输入,貌似无穷尽。
所以,这一关肯定不能采取手动输入的方法闯关,自然要用到 Python 了。要实现自动填充修改 url 回车跳转到新 url,循环直到网页再也无法跳转为止这一功能。
如果是你,你会怎么做?
【提示】其实,一段简单的爬虫加正则就能搞定。思路很简单,把每次网页中的数值提取出来替换成新的 url 再请求网页,循环下去,代码实现如下:
1 import requests 2 import re
3 import os 4 5 # 首页url 6 resp = requests.get( 7 'http://www.pythonchallenge.com/pc/def/linkedlist.php?nothing=12345' ).text 8 url = 'http://www.pythonchallenge.com/pc/def/linkedlist.php?nothing=' 9 # 计数器 10 count = 0 11 while True :12 try :13 # 提取下一页动态数值 14 nextid = re.search('\d+' , resp).group()15 count = count + 1 16 nextid = int(nextid)17 except :18 print('最后一个url为:%s' % nexturl)19 break 20 21 # 获取下一页url 22 nexturl = url + str(nextid)23 print('url %s:%s' % (count, nexturl))24 # 重复请求 25 resp = requests.get(nexturl).text
输出结果如下:
可以看到,最终循环了 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/