pythonchallenge(三)

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.zip
2 $ unzip -l channel.zip

文件内容如下:

一共有910个文件,大多数文件的命名都是数字型,解压并查看说明文档`readme.txt`

1 $ unzip channel.zip 
2 $ vi readme.txt

根据上面的提示,我们了解到两个信息:

  1. 循环是从`90052.txt`这个文件开始;
  2. 答案就隐藏在zip压缩包文件夹的内容中。

查看`90052.txt`这个文档内容如下:

看到这句话的时候,你是不是觉得似曾相识?是的,在上一个挑战项目中也出现过这么一句话,区别在于上一次的题目是使用`urllib`模块在网页上寻找关键字,这一次是在压缩包内寻找答案。

算法如下:

  • 1. 设置初识起点,进入循环,使用正则表达式匹配文件内容中的数字;
  • 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 text
13         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         break
17     print "".join(comments) # 打印所有注释信息    

那么答案应该就是`hockey`了,转到该链接:

然后提示让我们看一下字母,并且提示该单词指的是存在于空气中。上面组成`HOCKEY`的图中恰好是由字母`O C Y G E N`组成,也就是单词空气——`oxygen`。

因此来到[下一题]

 

五、第七个挑战题

问题:根据这副图片找到通往下一个链接的单词。

**小编脑洞:**

然而这一次源代码中并没有提供额外的信息,那么只能看图,仔细观察上图,发现这个图并不完整,图的中间被一条不同深度的灰度长条给掩盖,那么信息很可能就隐藏在这里面。那么图像处理中我们知道每一个图片都是由无数个像素值组成,实际上就是一个[像素]构成的矩阵,那么答案很可能与这些像素值有关。关于这个问题的具体思路,有兴趣的朋友可以看一下我的[博客]

首先下载用于处理图像的`Image`模块,然后下载本题所需要处理到的图片`oxygen.png`。

1 $ sudo apt-get install python-imaging
2 $ wget http://labfile.oss.aliyuncs.com/courses/411/oxygen.png


输入以下代码观察图片的大小:

1 import Image
2 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 bz2
2 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`这种格式的字符串是一种压缩形式,然后进行相应的解压就可以解决问题。

 八、任务

问题:请把点连接起来,[题目链接](提示:源代码,源代码!)。

 

posted @ 2015-08-14 17:13  wing1995  阅读(426)  评论(0编辑  收藏  举报