​一个超有意思的 Python 综合能力测试网站

 

这一期的话题是:一个学习 Python 的趣味网站

最近在网上看到一个非常有意思的 Python 游戏通关网站,一共有 33 关,每一关都需要利用 Python 知识解题找到答案,然后进入下一关。很考验对 Python 的综合掌握能力,比如有的闯关需要用到正则表达式,有的要用到爬虫。
 

我们平常学 Python 都是按章节顺序、包或者模块来学,容易前学后忘。正好可以拿这个网站来综合测试一下对 Python 的掌握情况,以便查缺补漏。

来说说这个网站怎么玩。

​一个超有意思的 Python 综合能力测试网站

mark

这是网站主页面,很有历史感对吧,诞生了已有十几年了。但千万不要因为看着像老古董而小瞧它。

​一个超有意思的 Python 综合能力测试网站
mark

我们来玩玩看,点击「get challenged」开始挑战。

第 0 关是 Warming up 热身环节:

这一关要求是修改 URL 链接,给的提示是电脑上的数学表达式:2 的 38 次方,所以大概就是需要计算出数值,然后修改url 进入下一关。

所以这关就是考 Python 的基本数值运算,你知道怎么算么?

打开 Python 自带终端,一行代码就能计算出结果:

​一个超有意思的 Python 综合能力测试网站

mark

把原链接中的 0替换为 274877906944回车就会进入下一关:

​一个超有意思的 Python 综合能力测试网站

mark

游戏这就正式开始了。图片中的笔记本给了三组字母,很容易发现规律:前面的字母往后移动两位就是后面的字母。

那么需要做的就是根据这个规律把下面的提示字符串,做位移解密得到真正的句子含义:

这道题考察字符串编码和 for 循环相关知识,代码实现如下:

 1text='''gfmncwmsbgblrrpylqjyrcgrzwfylb.rfyrqufyramknsrcpq 2ypcdmp.bmglegrglzwfylbgqglcddgagclrylbrfyr'q 3ufwrfgqrcvrgqqmjmle.sqgleqrpgle.kyicrpylq() 4gqpcamkkclbcb.lmuynnjwmlrfcspj.''' 5 6text_translate='' 7foriintext: 8ifstr.isalpha(i): 9n=ord(i)10ifi>='y':11n=ord(i)+2-2612else:13n=ord(i)+214text_translate+=chr(n)15else:16text_translate+=i17print(text_translate)

得到结果:

1ihopeyoudidnttranslateitbyhand.2thatswhatcomputersarefor.3doingitinbyhandisinefficientandthat'swhythistextissolong.4usingstring.maketrans()isrecommended.nowapplyontheurl.

作者很风趣,当然不能手动去一个推算了,推荐用 string.maketrans() 这个方法解决,我们上面采取的是比较直接的方法,官方给出了更为精简的方法:

1importstring2l=string.lowercase3t=string.maketrans(l,l[2:]+l[:2])4print(text.translate(t))

然后把 url 中的 map 改为ocr回车就来到了第 2 关:

​一个超有意思的 Python 综合能力测试网站
mark

作者接着说过关的提示可能在书里(当然不可能了)也可能在网页源代码里。那就右键查看源代码往下拉看到绿色区域,果然找到了问题:

​一个超有意思的 Python 综合能力测试网站
mark

意思就是:要在下面这一大串字符里找到出现次数最少的几个字符

考察了这么几个知识点:

  • 正则表达式提取字符串
  • list 计数
  • 条件语句

如果是你,你会怎么做?

来看下,十行代码快速实现:

 1importrequests 2url='http://www.pythonchallenge.com/pc/def/ocr.html' 3res=requests.get(url).text 4text=re.findall('.*?<!--.*-->.*<!--(.*)-->',res,re.S) 5#list转为str便于遍历字符 6str=''.join(text) 7 8lst=[] 9key=[]10#遍历字符11foriinstr:12#将字符存到list中13lst.append(i)14#如果字符是唯一的,则添加进key15ifinotinkey:16key.append(i)17#将list列表中的字符出现字数统计出来18foritemsinkey:19print(items,lst.count(items))

首先,用 Requests 请求网页然后用正则提取出字符串,接着 for 循环计算每个字符出现的次数。

 1%6104 2$6046 3@6157 4_6112 5^6030 6#6115 7)6186 8&6043 9!607910+606611]615212*603413}610514[610815(615416{60461718e119q120u121a122l123i124t125y1

可以看到出现次数最少的就是最后几个字符,合起来是「equality」,替换 url 字符就闯过过了第 2 关进入下一关继续挑战。是不是有点意思?

后面每一关都需要用到相关的 Python 技巧解决,比如第 4 关:

​一个超有意思的 Python 综合能力测试网站

mark

这一关作者弄了个小恶作剧,需要手动输入数值到 url 中然后回车,你以为这样就完了么?并没有它有会不断重复弹出新的数值让你输入,貌似无穷尽。

​一个超有意思的 Python 综合能力测试网站

所以,这一关肯定不能采取手动输入的方法闯关,自然要用到 Python 了。要实现自动填充修改 url 回车跳转到新 url,循环直到网页再也无法跳转为止这一功能。

如果是你,你会怎么做?

其实,一段简单的爬虫加正则就能搞定。思路很简单,把每次网页中的数值提取出来替换成新的 url 再请求网页,循环下去,代码实现如下:

 1importrequests 2importre 3importos 4 5#首页url 6resp=requests.get( 7'http://www.pythonchallenge.com/pc/def/linkedlist.php?nothing=12345').text 8url='http://www.pythonchallenge.com/pc/def/linkedlist.php?nothing=' 9#计数器10count=011whileTrue:12try:13#提取下一页动态数值14nextid=re.search('d+',resp).group()15count=count+116nextid=int(nextid)17except:18print('最后一个url为:%s'%nexturl)19break2021#获取下一页url22nexturl=url+str(nextid)23print('url%s:%s'%(count,nexturl))24#重复请求25resp=requests.get(nexturl).text

输出结果如下:

​一个超有意思的 Python 综合能力测试网站

可以看到,最终循环了 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/


END

发表评论