记录解谜 Python 练习

在日志拼图练习中,您将使用 Python 代码解开两个谜题。本练习使用 urllib 模块,如 Python 实用程序部分中所示。此练习的文件位于 google-python-exercises 内的“logpuzzle”目录中(如果您还没有下载 google-python-exercises.zip,请参阅设置了解详情)。将您的代码添加到“logpuzzle.py”文件中。

某张动物图片被拆分成了许多狭窄的纵向条纹图片。条纹图片位于互联网上的某个位置,每张图片都有自己的网址。这些网址会隐藏在网络服务器日志文件中。您的任务是找到网址并下载所有图片条纹,以重新创建原始图片。

切片网址隐藏在 Apache 日志文件中(开源 apache Web 服务器是互联网上使用最广泛的服务器)。每个日志文件都来自某个服务器,并且所需的切片网址隐藏在日志中。该日志文件会按如下方式对源服务器进行编码:日志文件“Animal_code.google.com”来自 code.google.com 服务器(以前,我们会说服务器名称是第一个下划线后的名称)。“Animal_code.google.com”日志文件包含“动物”益智图片的数据。虽然日志文件中的数据采用真正的 Apache 网络服务器的语法,但谜题所需的数据之外的数据是来自真实日志文件的随机数据。

日志文件中某一行的内容应如下所示(apache 日志文件实际如下所示):

10.254.254.28 - - [06/Aug/2007:00:14:08 -0700] "GET /foo/talks/ HTTP/1.1"
200 5910 "-" "Mozilla/5.0 (X11; U; Linux i686 (x86_64); en-US; rv:1.8.1.4) Gecko/20070515 Firefox/2.0.0.4"

前几个数字是发出请求的浏览器的地址。最有趣的部分是“GET path HTTP”,它显示了服务器收到的网络请求的路径。路径本身不包含空格,并且通过空格与 GET 和 HTTP 分隔(正则表达式建议:\S(大写 S)匹配任何非空格字符)。在日志中找到字符串“puzzle”显示在路径中的各行,并忽略日志中的许多其他行。

A 部分 - 日志文件到网址

完成从日志文件中提取谜题网址的 read_urls(filename) 函数。在日志文件中查找所有“谜题”路径网址。将每个网址的路径与文件名中的服务器名称结合起来,形成完整的网址,例如“http://www.example.com/path/puzzle/from/inside/file”。过滤掉多次出现的网址。read_urls() 函数应返回完整网址的列表,该列表按字母顺序排列且不重复。按字母顺序获取网址将会以正确的从左到右顺序生成图片切片,从而重新创建原始的动物图片。在最简单的情况下,main() 应该只输出网址,每行一个。

$ ./logpuzzle.py animal_code.google.com
http://code.google.com/something/puzzle-animal-baaa.jpg
http://code.google.com/something/puzzle-animal-baab.jpg
...

B 部分 - 下载拼图图片

完成 download_images() 函数,该函数接受已排序的网址列表和目录。将各个网址中的图片下载到给定目录中,必要时先创建目录(如需创建目录,请参阅“os”模块;如需下载网址,请参阅“urllib.urlretrieve()”)。使用“img0”“img1”“img2”等简单的格式为本地图片文件命名。下载每张图片时,您可能需要输出一个“正在检索...”状态输出行,因为下载速度会很慢,而且最好表明程序可以运行。每张图片都是从原始图片中分离出来的一小块纵向图片。如何将切片组合在一起,以重新创建原始版本?只需少量 html 即可很好地解决此问题(不需要掌握 HTML 知识)。

download_images() 函数还应在 目录中创建一个具有 *img* 标记的 index.html 文件,以显示每个本地图片文件。img 标记应全部放在一行上,不进行分隔。通过这种方式,浏览器可以无缝地显示所有切片。您不需要了解 HTML 也能进行此操作;只需创建一个如下所示的 index.html 文件即可:

<html>
<body>
<img src="img0"><img src="img1"><img src="img2">...
</body>
</html>

以下是下载动物谜题的样子:

$ ./logpuzzle.py --todir animaldir animal_code.google.com
$ ls animaldir
img0  img1  img2  img3  img4  img5  img6  img7  img8  img9  index.html

一切正常后,在浏览器中打开 index.html 应该会显示原始的动物图片。图片中的动物是什么?

C 部分 - 图片切片解扰

第二个谜题涉及一个非常有名的地方的图片,但依赖于一些自定义排序。对于第一个谜题,可以按字母顺序对网址进行排序,以便正确对图片排序。在排序时,将使用整个网址。不过,如果网址以“-wordchars-wordchars.jpg”格式(例如“http://example.com/foo/puzzle/bar-abab-baaa.jpg”)结尾,那么该网址应由排序中的第二个字词(例如“baaa”)表示。因此,对以 word-word.jpg 格式结尾的网址列表进行排序时,应按第二个字词对网址进行排序。

扩展您的代码以对此类网址进行正确排序,然后您就应该能够对显示著名地点的第二个 place_code.google.com 谜题进行解码了。显示什么地点?

字幕署名:此谜题中使用的图片是由其所有者根据知识共享署名 2.5 许可提供的,该许可在很大程度上鼓励他人对此类内容进行混剪。动物图片来自 Flickr 的用户 zappowbang,地点图片来自 flickr 的用户 booleansplit。