继续挑战,又是很抽象
第18题地址balloons.html
- 网页标题是
can you tell the difference?
,题目内容为空,源码中有一行隐藏信息:<!– it is more obvious that what you might think –>
图片是由大致相同的一明一暗两张图组成的。
标题说你能找出不同么?
,还提示说比你想的还要明显
,这该不会是来找茬吧?
想到这两张图是有明暗差别的,估计还是图像处理:
from io import BytesIO
from itertools import product
import requests
from PIL import Image
with requests.Session() as sess:
sess.auth = ('huge', 'file')
response = sess.get('http://www.pythonchallenge.com/pc/return/balloons.jpg').content
img = Image.open(BytesIO(response))
width, height = img.size
img_diff = Image.new(img.mode, (width // 2, height))
img_diff_data = img_diff.load()
img_data = img.load()
for x, y in product(range(width // 2), range(height)):
left = img_data[x, y]
right = img_data[x + width // 2, y]
img_diff_data[x, y] = tuple(l - r for l, r in zip(left, right))
img_diff
还是那张图啊!
该不会还有更明显的结论吧?
试试亮度brightness.html,居然打开了另外一个一模一样的页面,但是源码里面隐藏信息不一样:
<!– maybe consider deltas.gz –>
好了,不多说,这个deltas.gz才是这个题目的重头戏。
我们下载下来看看:
import gzip
from io import BytesIO
import requests
with requests.Session() as sess:
sess.auth = ('huge', 'file')
response = sess.get('http://www.pythonchallenge.com/pc/return/deltas.gz').content
with gzip.open(BytesIO(response)) as f:
deltas = f.read().decode()
for i, line in enumerate(deltas.splitlines()):
if i % 100 == 0:
print(line)
89 50 4e 47 0d 0a 1a 0a 00 00 00 0d 49 48 44 52 00 00 89 50 4e 47 0d 0a 1a 0a 00 00 00 0d 49 48 44 52 00 00
9c bf da 23 d4 30 b9 ca 4b 1a a4 94 02 68 b8 59 f2 7c 02 07 0f d7 bf ae 09 a5 2d b7 1e ce e1 c3 c3 b3 82 1a
e4 d3 5a 28 63 48 43 a9 15 1d 83 b5 02 94 42 4e 19 ca 37 5c 37 dc 1c fb 67 57 e1 f2 4d 1c 75 40 58 f3 6a 11
0d 57 88 ab 1d 1d f3 6f 79 ea 6d a6 0d ec 62 02 dd 3a 9a 22 33 b0 1a 26 41 22 b4 8a b8 91 38 b8 15 3e a3 12
dc 08 c4 83 19 9f 59 30 19 c3 f3 1b 91 50 56 a9 61 4e d5 3f 8d 1d 5a 80 3c fb 8b 6f 34 63 bb b9 2a 50 d6 9c
e9 ce 71 f5 b9 97 18 65 1f e8 48 bb 1e 30 be b8 c4 f6 d3 13 3c 7f b5 14 4e 28 91 d8 3c 50 c3 84 52 b3 a9 c8
50 09 a5 13 b5 fb c0 7c 7f a0 8f 72 2a 1c 9c 14 cd 2d 4b fe 8c f2 48 0d 3d 50 a3 df 99 3f fe de fe f3 8e da
25 4f fb f0 f1 6a 8b f1 eb 8b 3b 1b a2 e9 c6 52 eb e5 f6 70 50 63 bd c6 52 16 93 3b 74 5f ef 04 c1 4b 38 e7
eb 0b 84 8b cd 9d 0e 6e 94 56 d0 3d 1b 59 5b ea 3f df 72 dd bb 1a 69 e8 a9 de 1b a9 c9 81 3e 22 90 21 23 3e
3c 22 3b c7 87 8b 35 55 45 5a ed 09 36 67 5e 3b d4 c0 af c3 d5 df ba 3f 3f 75 8f 6e 21 36 f7 2f b9 de b2 b5
32 d1 ef ba 7e 15 13 ec fe 91 fe a5 c4 a0 40 59 d2 c0 3a 61 44 a5 3d fc 6b 43 04 d6 c2 06 0a 15 0f 3f 80 b4
f9 88 8d 14 09 a5 87 fa 68 aa f6 2c 12 43 9b 4f b4 39 a6 56 87 b4 0c c1 d4 6c 22 ad 52 3a 95 e8 05 22 67 4a
b0 cb cb 39 d3 35 0c d4 f6 48 83 27 27 fa cd 28 d1 ca a5 c4 52 a2 61 0c 69 03 9b 50 da 72 d3 52 3d 55 7b 03
d2 05 e6 b7 ef 17 7d 12 09 18 52 c9 94 1e a4 41 28 b3 73 cc 12 2c ee fe 63 c9 91 cd 31 2d 51 48 75 b7 55 5f
be af d9 df 0f 4d eb ae d0 ba ea 61 e3 76 ac 3d e2 fa c0 74 a2 07 ce dd c5 be aa 75 16 bb ac 7f ca ba 12 bd
83 95 c9 a3 a7 5f 7d 16 d9 ce 36 57 6e 16 23 97 62 e0 4c cb ce e4 66 17 7b 52 a7 ee 78 8e 0e a0 14 bd 3b 12
14 33 9e 88 36 6a 89 32 e1 85 58 74 c8 4d 75 86 e3 37 3d e2 d0 d0 f2 70 2d 45 66 0f 1e 33 4b f6 2c 69 ae 24
26 7c b9 c0 ec e1 6b ac 15 ca 98 e7 20 ac aa 83 49 69 71 3c ed 2c 81 f0 c4 08 f4 d7 18 71 c8 f7 21 11 41 ab
80 d0 27 df a7 40 1e 67 44 64 b9 ae b9 b2 b0 0b 9e 3e 51 70 3e 75 93 c7 9e e9 b8 17 39 d2 23 7e ff 0a af 43
d1 97 a7 41 07 9e cc 99 37 aa ef 0c 20 5d 6b 65 4b dc b3 47 cf b7 b0 2b 3f b7 10 91 e8 bb 89 82 ac 0c de a3
e7 d5 37 3f c3 e4 1d ff 10 51 c7 72 3d a2 0d 91 c6 94 fc 9b 8a cd 52 02 91 82 ad 08 bc 5b d4 dc f8 32 49 35
18 90 07 8a 03 29 5e a3 54 09 8f fb a9 bd e0 41 43 71 3b 8f 79 f1 71 ee 2e a7 87 12 45 8e cc 63 1f c4 15 aa
51 14 45 51 14 45 51 14 45 51 14 45 51 14 45 51 14 45 ed 51 fd 7e e2 2e 0b ce ff be 9e dd df fc f1 bc f6 48
我们可以看到,这个delta
数据分为左右两部分,有很大一部分是一样的,也有一部分是不一样的。
结合这题的标题,应该是要用文本比较工具找出它们的不同之处:
from difflib import Differ
split_lines = deltas.splitlines()
left, right = [line[:53] for line in split_lines], [line[56:] for line in split_lines]
diff = Differ().compare(left, right)
for i, d in enumerate(diff):
if i % 100 == 0:
print(d)
89 50 4e 47 0d 0a 1a 0a 00 00 00 0d 49 48 44 52 00 00
9c bf da 23 d4 30 b9 ca 4b 1a a4 94 02 68 b8 59 f2 7c
6c df d5 e8 b8 53 a4 6a 5f 47 2a ec ce c2 90 dd 51 7b
- 11 66 da 22 0d 1e 9b df 7f 75 27 95 9e 6e e9 3e e8 ce
48 ac f2 2c d9 8c 8a 18 a1 ef 5a e9 6c 6e f8 bb 75 dc
+ 02 01 83 11 e8 95 11 e8 ae 32 12 09 ce 61 a2 6c 29 49
- 19 30 7e 7d 01 a5 15 99 92 f4 bc 87 0e 20 f9 88 b4 19
+ 9d f7 2f 4d 67 aa 0a f7 ea 1a f7 9b 06 b7 e8 af 10 54
fe 77 e6 c7 23 fd 5d a5 06 e2 82 5b f3 3a e5 66 15 16
+ 76 58 55 d8 65 c3 b2 e1 3d a2 cb 0d 45 22 2b 92 a7 90
- 7a e8 39 65 9e e7 0e ec 2a 94 49 c6 14 23 c0 c7 d1 9c
+ a6 07 20 d3 49 77 ab 0a b1 14 ec 79 8f 5b 75 3d d7 2e
- 2a ed 4a 19 30 f4 66 a0 1b 4a 22 0d e7 6b 7a 13 ba 8f
+ 25 86 10 50 f3 41 d9 0f 01 5f b5 2d 9e c6 88 15 bb cc
6c 3a b5 bc e1 96 6b ac 3a b4 0b 9e 37 af cb 3f 2c 92
2e 8e f1 74 80 51 df fe 94 cc c6 22 91 91 a7 82 aa 11
+ 55 04 f4 5f 77 1d fe f3 ee 2e ee d0 53 40 3b d6 6f de
6c 35 ea 56 3a ed e9 bf 4a 29 3b 37 67 91 ba 6a 46 38
- 32 44 e0 fd f1 f7 ed c8 6e 26 0d dc d9 02 93 4f cf d0
- cc 43 b8 0a 8d 9b 11 e3 8b 4b ac fe e7 7f 42 3b 83 fe
7b 03 6f 6c 36 46 66 1c d2 72 b4 a4 55 b7 b7 b0 32 96
- 23 76 7f 78 01 a4 5c 75 ae 48 19 aa b5 48 83 af 7e a1
ad 01 34 03 74 52 fc ef a0 db a5 be cf fe ed e7 95 5d
72 ff a4 88 6f 2f bd 14 9c d7 54 4b ca cb cb 8a 3d 5a
84 1c b5 09 7a 89 e2 f6 a7 e4 10 e3 17 f8 6e 35 36 ff
+ a7 6d e2 94 3f eb 32 45 54 df 2b 24 71 9c 12 3a 3a f7
68 cf dc 4d cf ed c9 95 bb a8 f8 7e 43 34 cb 94 85 ef
c8 71 c8 ef 40 78 c1 3f 97 25 c1 52 96 e4 8b 2c 7d fd
ed 51 fd 7e e2 2e 0b ce ff be 9e dd df fc f1 bc f6 48
51 14 45 51 14 45 51 14 45 51 14 45 51 14 45 51 14 45
我们把相同(
)、左边有右边没有(-
)、左边没有右边有(+
)的分别收集起来并且将其转换成bytes
形式:
def hex2bytes(data: str) -> bytes:
return bytes(int(s, 16) for s in data.split())
diff = Differ().compare(left, right)
same = bytearray()
plus = bytearray()
minus = bytearray()
for d in diff:
code = d[0]
data = d[2:]
if code == ' ':
same.extend(hex2bytes(data))
elif code == '-':
minus.extend(hex2bytes(data))
elif code == '+':
plus.extend(hex2bytes(data))
print(same[:20])
print(plus[:20])
print(minus[:20])
bytearray(b'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x02\x8a')
bytearray(b'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x01P')
bytearray(b'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x01P')
很惊奇地发现,这三部分都是PNG
图片的文件头。让我们来看看是什么东东:
from PIL import Image
from matplotlib import pyplot as plt
%matplotlib inline
for i, b in zip(range(3), (same, plus, minus)):
img = Image.open(BytesIO(b))
plt.subplot(1, 3, i + 1)
plt.imshow(img)
plt.axis('off')
分别是../hex/bin.html,butter
和fly
。
网址打开之后要求输入密码,提示是pluses and minuses
,尝试用户名butter
和密码fly
便来到了下一题!