pythonchallenge(二)

PythonChallenge_2

一、实验说明

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官网],课程编写属于实验楼原创,欢迎在问答区积极提问,小编会积极解答,也欢迎在评论区吐槽~

三、实验回顾

在上一个[项目课]中,我们学到了很多知识,比如:`string`模块中的一些函数,字典的使用以及函数`lambda`。记性不算太差的你们估计还记得在上一次的课程中小编有留给大家一个课后作业,不知道你们完成的怎样呢?

不管是否得到答案,让小编带着你一起解决这个问题吧!

四、作业题解析

问题:找出满足以下条件的字母:字母是小写的,在该字母两边各有3个大写字母做保镖。

**小编脑洞:**

第一眼看到该图片的感觉是,确实图片中的几根蜡烛生动形象的描述了大小写字母的关系,那么是哪些字母,图片并没有明确的表示,看来只有看源代码了。

依旧是一大堆乱七八糟的字符,与上一个问题的字符内容不同的时候,这里面的字符是由大小写英文字母组成。

这里有一个误区,通往下一个网页的关键单词的组成字母存在于这样的字符串`XXXxXXX`中,并且那些字母就是被那3个大写字母包围的小写字母,重新审核他给的原问题:

`One small letter, surrounded by EXACTLY three big bodyguards on each of its sides.`

注意里面的单词`EXACTLY`,也就是说刚好是`3`个大写字母而不是`4`个大写字母,因此为了确保,旁边三个大写字母两边必须分别是一个小写字母!所以答案就很明显了,该单词的字母存在于由9个字母组成的字符串中,排列形式是`xXXXxXXXx`。也就是说从网页源码的一大堆杂乱的字符串中找出符合`xXXXxXXXx`这样排列的子字符串就可以得出需要的小写字母,然后将那些满足条件的小写字母连接好就是通往答案的单词。

首先,那一堆乱七八糟的字符已经上传到实验楼的服务器上了,大家输入以下命令行下载文档:

1 wget http://labfile.oss.aliyuncs.com/courses/409/character.txt

废话有点多,看看大神们的解决方案:

**方法一:正则匹配,最简单粗暴的方式**

1 import re
2
3 text = open(‘character.txt‘).read()
4
5 "".join(re.findall(‘[^A-Z][A-Z]{3}([a-z])[A-Z]{3}[^A-Z]‘,tetx))

这里用到了正则表达式`re`模块,关于正则表达式的内容,推荐学习[30分钟入门正则表达式],里面的正则表达式测试工具也是相当好用,以下介绍正则语句`[^A-Z][A-Z]{3}([a-z])[A-Z]{3}[^A-Z]`:

1. 首先,函数`re.fidall(regex,str)`是返回所有`str`内容中被正则语句`regex`匹配的所有字符串;

2. `[^A-Z]`是匹配一个非大写字母;

3. `[A-Z]{3}`指的是匹配3个连续的大写字母;

4. `[a-z]`匹配一个小写字母。

**方法二:使用`string`模块,最常规的方法**

 1 import string
 2
 3
 4
 5 s = open(‘character.txt‘,‘r‘).read()
 6
 7 lwr=string.lowercase
 8
 9 upr=string.uppercase
10
11
12
13 for n in range(1,len(s)-7):
14
15     if (s[n-1] in lwr) and (s[n] in upr) and (s[n+1] in upr)16
17     and (s[n+2] in upr) and (s[n+3] in lwr)18
19     and (s[n+4] in upr) and (s[n+5] in upr)20
21     and (s[n+6] in upr) and (s[n+7] in lwr):
22
23         print s[n+3]

该方法没有讲究什么技巧,直接判断是否存在满足条件`xXXXxXXXx`的字符,然后把最中间的那个小写字母`x`给打印出来。

**方法三:使用`reduce`函数调用子函数处理字符串**

创建一个`test_0.py`文件,编写代码:

# coding:utf-8

def level_3(state, c):

         if not c.isalpha():  # 先判断字符是否为是字母

                   return state

         if state: # 如果元组不为空

                   chars_found, state_lower, upper_count = state

         else:

                   state_lower = ""

                   upper_count = 0

                   chars_found = ""

         if c.islower():  # 如果字符是小写字母

                   if upper_count == 3:  # 如果大写字母的数量为3

                            if state_lower:  # 如果找到符合条件的小写字母

                                     chars_found += state_lower

                            state_lower = c

                   else: 

                            state_lower = ""

                   upper_count = 0

         else:

                   upper_count += 1

         return chars_found, state_lower, upper_count

if __name__ == "__main__":

    with open(‘character.txt‘) as f:

        s = f.read()

    s += "x" # 最右边添加一个小写字母

    print reduce(level_3, str, ())[0]

关于`reduce`函数,可以使用`help`命令查阅该函数的英文文档。用法如下:

  • `reduce(function, sequence[,initial])`函数中有两个参数和一个可选参数;`function`参数是一个函数,`sequence`参数是一个序列,使用`reduce`函数可以给函数`function`提供参数进行累加,参数来源于序列`sequence`的元素;
  • - 比如:`reduce(lambda x, y: x+y, [1, 2, 3, 4, 5])`就是计算`((((1+2)+3)+4)+5)`;也就是`function`的结果和``sequence`中下一个序列元素作为`function`的参数;
  • - `initial`参数如果被给出,那么它将作为初始化结果,缺省情况下是空的。

那么应用在`test_0.py`文件中的`reduce`函数的作用就是,使用`level_3`函数对字符串`s`中的每一个字母进行处理,且函数初始返回结果`state`为空元祖`()`。

五、第4个挑战题

**小编脑洞**

这一次的题目没有给任何提示,只是上面的一张图片,图片的名字为`chainsaw`,意思是`肢解,用链锯隔开`,那么是不是意味着接下来的东西是一个`链`?

经过这几次闯关,我们知道一般答案都隐藏在网页源代码中,审查元素,发现:

首先,有提示说,使用`urllib`或许能帮助我们,但是不要一直追踪链接,因为一直点击链接是没有终止循环的那一天,因为链接数量超过400个。

那么答案应该就是隐藏在链接中,刚好在图片的下面找到一个`href`链接语句:`a href="linkedlist.php?nothing=12345"`那么点击这个[链接]查看结果:

提示下一个`nothing`的值为44837,那么把链接地址:http://www.pythonchallenge.com/pc/def/linkedlist.php?nothing=12345中的`nothing`值改为`44837`就是了,其实这个时候不用查看链接的结果也知道,下一个页面也是这样提示`nothing`的值,根据源代码中的提示,这个链接不超过400个,因此如果手动点击400次会非常浪费时间而且无聊,那么就使用`Python`的`urllib`模块玩一玩吧~

关于这个题目,因为要访问外网才能遍历链接,因此在这里只介绍一种方法,希望你们在自己的电脑上进行编程验证代码,并用自己的方式解决这个问题:

 1 import urllib
 2
 3 import urllib2
 4
 5
 6
 7 data= {}
 8
 9 number = ‘12345‘
10
11
12
13 # 循环400次
14
15 for i in range(400):
16
17     # 给字典`data`中的`nothing`赋初始值
18
19          data[‘nothing‘] = number
20
21          url_values = urllib.urlencode(data)
22
23          url = ‘http://www.pythonchallenge.com/pc/def/linkedlist.php‘
24
25          full_url = url + ‘?‘ + url_values
26
27
28
29          foo = urllib2.urlopen(full_url)
30
31          foo = foo.read()
32
33          print foo  # 打印网页内容
34
35          foo = foo.split(" ")  # 使用空格作为分隔符分开单词
36
37
38
39          number = [i for i in foo if i.isdigit()][0]

然后就会循环400次打印捕捉到的网页内容

然后你根据这些内容跳链接,实际上这种方式有障碍,那就是遇到网页内容中没有数字的内容时会报错,例如在上面的脚本运行一段时间后会打印以下内容:

注意看最后一句,`Yes. Divide by two and keep going.`该句中没有任何数字而是提示,需要将前一个数字除以2才能继续前进。

遇到这种情况,通常是把初始的`number`改为`92118/2`,但是这样显得不怎么`pythonic`,而且,一般答案应该是给一个链接比如内容应该是以`.html`结尾的,因此需要把以上情况都考虑到原始脚本的条件中,修改以上脚本:

 1 import re
 2
 3 import urllib
 4
 5
 6
 7 url="http://www.pythonchallenge.com/pc/def/linkedlist.php?nothing="
 8
 9
10
11 nothing = "12345"
12
13 # 匹配以数字结尾的字符串以继续搜索
14
15 search = re.compile(" (\d*)$")
16
17 匹配最终的网页类型字符串以跳出循环
18
19 search_html = re.compile("\.html$")  #
20
21
22
23 for i in xrange(400):
24
25     print "%s: " % nothing,
26
27
28
29     line = urllib.urlopen( "%s%s" % (url,nothing) ).read()
30
31     print line
32
33
34
35     # 如果找到最终的网页链接则终止查询
36
37     if search_html.findall (line):
38
39         break
40
41
42
43     match = search.findall (line)
44
45     if match:
46
47         # 下一个nothing值
48
49         nothing = match [0]
50
51     else:
52
53         # 上一个nothing除以二
54
55         nothing = str(int(nothing) / 2)

其实这个题目的原理很简单,一直搜索链接,遇到数字就进入下一次搜索,遇到非数字就考虑是否是`.html`结尾,不是就给上一个数字除2继续搜索。

六、第5个挑战题

问题:读出来

**小编脑洞**

依旧源代码:

注意语句:`<peakhell scr="banner.p">`以及`peak hell sound familiar?`

了解到应该是一个跟`peak hell`读音非常接近的`Python`用法,由于`banner.p`是一个文件,那么文件处理中跟`peak hell`发音相似的只有`pickle`模块,那么问题就很明显了,应该就是让我们使用`pickle`模块对`banner.p`文件进行处理,答案应该就隐藏在经过处理后的字符串中。

那么小编已经把文件`banner.p`放在个人的`git`仓库中了,请输入以下命令下载文件并查看:

1 git clone http://git.shiyanlou.com/wing1995/shiyanlou_cs409
2
3 cd shiyanlou_cd409
4
5 ls

`pickle`模块介绍:

  • > `python`的`pickle`模块实现了基本的数据序列和反序列化。通过`pickle`模块的序列化操作我们能够将程序中运行的对象信息保存到文件中去,永久存储;通过`pickle`模块的反序列化操作,我们能够从文件中创建上一次程序保存的对象。

由于数据文件有了,那么要做的就是使用`pikle`模块中`load()`函数从文件中重构`python`对象:

 1 import pickle
 2
 3
 4
 5 # 以二进制形式读取文件内容
 6
 7 data = pickle.load(open(‘banner.p‘, ‘rb‘))
 8
 9 for each in data:
10
11     print each

观察数据打印结果:

结果是一个列表,列表里面的数据非常有规律,列表里面包含有多个子列表,子列表的内容是由一到多个元组组成,那些元祖里面都是只有2个元素,第一个元素是字符型,要么是`‘ ‘`,要么是`‘#‘`,第二个元素是数字,仔细分析这些子列表,发现:

很有意思,都是有规律的,猜测:子列表中每一个元祖代表字符(第一个元素)出现的次数(第二个元素)。

尝试打印:

1 for each in data:
2
3     "".join([i[1] * i[0] for i in each])

见证奇迹的时刻到来了:

额,好吧,实验楼虚拟环境显示图不全,再来一张比较明显的:

这明明就是单词`channel`!

看来答案非常明显,把`url`链接中单词`peak`换成`channel`就好。所有大家看着这个字符图片是不是觉得很有意思,关于这个字符图画的拓展课程,实验楼也已经写好,在[Python图片转字符画]

鉴于实验楼的命令行窗口显示不清楚,我们先把输出的字符写入到图片文件中查看字符画:

 1 import pickle, pprint
 2
 3 import Image, ImageDraw
 4
 5
 6
 7 im = Image.new("1", (95, 24))
 8
 9 draw = ImageDraw.Draw(im)
10
11 data = pickle.loads(s)
12
13 line = 0
14
15
16
17 for i in data:
18
19     xpos = 0
20
21     for j in i:
22
23         if j[0] == " ":
24
25             draw.line([(xpos,line), (xpos+j[1],line)], 255)
26
27         xpos += j[1]
28
29     line += 1
30
31 im.save("banner.bmp")

以上代码需要安装`Image`模块后才能实现,关于该模块的安装和学习在[课程Python图片转字符画][课程Python破解验证码]里面有详细介绍,欢迎各位学完那些课程再来查看以上代码是否更加熟悉。

当然,不一定要直接转成图片文件,也可以直接把字符串的输出结果写入到文件中。

七、作业

请完成以下作业,并写入实验报告,不一定要做出结果,但是一定要写出思路以及对这门课程的总结:

### 问题:请访问[挑战题链接]查看源代码,找到通往下一个网址的链接。(提示:与`zip`有关)

时间: 2024-10-01 02:24:42

pythonchallenge(二)的相关文章

Pythonchallenge一起来闯关(二)

前情提要:Pythonchallenge一起来闯关(一) 这一篇来闯关10-15.感觉这几关比先前的难了不少,有的题目完全没思路. 10. 页面源码中的链接点击后有a = [1, 11, 21, 1211, 111221, google之后知道这是一个叫做http://en.wikipedia.org/wiki/Look-and-say_sequence的数列.下面是一种比较简洁的解法. import re x="1" for each in range(5): print(x) l

pythonchallenge(三)

PythonChallenge_3 一.实验说明 1. 环境登录 无需密码自动登录,系统用户名shiyanlou,密码shiyanlou 2. 环境介绍 本实验环境采用带桌面的Ubuntu Linux环境,实验中会用到桌面上的程序: 1. LX终端(LXTerminal): Linux命令行终端,打开后会进入Bash环境,可以使用Linux命令2. Firefox:浏览器,可以用在需要前端界面的课程里,只需要打开环境里写的HTML/JS页面即可3. GVim:非常好用的编辑器,最简单的用法可以参

pythonchallenge(一)

PythonChallenge_1 一.实验说明 下述介绍为实验楼默认环境,如果您使用的是定制环境,请修改成您自己的环境介绍. 1. 环境登录 无需密码自动登录,系统用户名shiyanlou,密码shiyanlou 2. 环境介绍 本实验环境采用带桌面的Ubuntu Linux环境,实验中会用到桌面上的程序: 1. LX终端(LXTerminal): Linux命令行终端,打开后会进入Bash环境,可以使用Linux命令 2. Firefox:浏览器,可以用在需要前端界面的课程里,只需要打开环境

python接口自动化测试(二)-requests.post()

上一节介绍了  requests.get()  方法的基本使用,本节介绍  requests.post()  方法的使用: 本文目录: 一.方法定义 二.post方法简单使用 1.带数据的post 2.带header的post 3.带json的post 4.带参数的post 5.普通文件上传 6.定制化文件上传 7.多文件上传 一.方法定义: 1.到官方文档去了下requests.post()方法的定义,如下: 2.源码: 3.常用返回信息: 二.post方法简单使用: 1.带数据的post:

二维码扫码积分系统定制开发

微信积分系统 二维码扫码积分系统定制开发找丽姐[158.1816.6626/电微]二维码营销模式系统定制开发 微信扫二维码营销系统开发 扫码领积分系统开发 一.如何实现扫二维码领红包功能? 1.使用扫描二维码领取红包对活动进行设置,包括红包数量.红包金额.促销地区.中奖概率等. 2.将生成的二维码赋到商品上面并赋涂层,一方面可以起到保证二维码的一次性,另一方面也可以引起消费者的好奇心. 3.通过手机微信打开扫一扫,扫码商品二维码关注公众号并领取红包,如果参与分享还可以获得抽奖的机会. 二.微信扫

微信生成二维码 只需一个网址即刻 还有jquery生成二维码

<div class="orderDetails-info"> <img src="http://qr.topscan.com/api.php?text=http://123.net/index.php?s=/Home/Index/yanzheng/mai/{$dange.id}" style="width: 5rem; margin-bottom: 1rem;" > </div> http://qr.tops

家电二维码售后服务平台系统开发

家电二维码售后服务平台系统开发,家电二维码售后系统开发,小吴183.2071.6434微电,家电二维码售后软件开发,家电二维码售后平台开发. 互联网平台的节点有两大类型:第一基数节点,也就是弱连接的节点,其规模要大,越大越好,互联网的价值与节点数的平比成正比.第二活跃节点,也就是强连接的节点,其能量要强,越强越好,互联网的价值与其强度成正比. 一.家电维修行业"维修黑幕"层出不穷 记者从一位从事家电维修人士那里了解到,目前行业公认当前家电维修行业有陷阱,"维修黑幕"

MySQL(九)之数据表的查询详解(SELECT语法)二

上一篇讲了比较简单的单表查询以及MySQL的组函数,这一篇给大家分享一点比较难得知识了,关于多表查询,子查询,左连接,外连接等等.希望大家能都得到帮助! 在开始之前因为要多表查询,所以搭建好环境: 1)创建数据表suppliers 前面已经有一张表是book表,我们在建立一张suppliers(供应商)表和前面的book表对应. 也就是说 让book中s_id字段值指向suppliers的主键值,创建一个外键约束关系. 其实这里并没有达到真正的外键约束关系,只是模拟,让fruits中的s_id中

winform学习日志(二十三)---------------socket(TCP)发送文件

一:由于在上一个随笔的基础之上拓展的所以直接上代码,客户端: using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Net.Sockets; using Sys