题目看上去很简单,拿到5页的所有数字算总和就行,来分析一下
看到数字不是文本的形式,而是经过 base64编码
的图片形式,有些图片的 style
属性中有display: none
,表示该图片不予展示,观察 ajax 接口返回的源数据,看到是直接返回 html
源码,还有key
、value
等字符串,暂时不明确这些的用途
对比渲染前后的html数据,有如下的不同点:
img_number
后疑似 md5编码(长度为32)的字符串不见了
style
属性多了 display
在这里猜测是根据不同的img_number
值来判断该图片节点是否给予展示,因为返回的图片节点数量明显大于
网页所展示的数量
直接全局搜 img_number
,发现只有一个结果,加断点调试:
到这里逻辑就很清晰了,上面的操作就是:
把info
即 原始html数据赋值给 $('.number')
节点,也就是 <tr class="number">
根据 key
和 value
先进行 base64编码 再进行 MD5加密,计算出 j_key
,只要是class值等于j_key的节点,都设置display属性
hex_md5
即哈希md5算法
最后就是 removeClass
和addClass
两个操作,修改 img_number
的值
最后一步,要怎么识别出图片中的数字呢?第一个想到的是ocr
,但这里不必小题大做,这里只有十个数字,即代表只有十张不同的图片,而图片都是经过base64编码的,相同图片编码出来的结果是一致的,所以只需要设计一张映射表就行
代码整理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
| import requests import hashlib
from base64 import b64encode from parsel import Selector
yuanrenxue_headers = { "User-Agent": "yuanrenxue.project", "sessionid": "6nfyiexiutauob3e0s7jmrxtz8qfy68b", }
def img_ocr(src): """ 根据src后缀识别图像 """ if src.endswith("eCAAAAAElFTkSuQmCC"): return "0" elif src.endswith("HMAAAAAElFTkSuQmCC"): return "1" elif src.endswith("Dor0g3AH8BJlTqZkAngxQAAAAASUVORK5CYII="): return "2" elif src.endswith("HzjKAAAAAElFTkSuQmCC"): return "3" elif src.endswith("QAAAABJRU5ErkJggg=="): return "4" elif src.endswith("cHAAAAAASUVORK5CYII="): return "5" elif src.endswith("0YzEyuMQpQAAAAASUVORK5CYII="): return "6" elif src.endswith("HrJiVs0AAAAAElFTkSuQmCC"): return "7" elif src.endswith("6cpuRANAAAAAElFTkSuQmCC"): return "8" elif src.endswith("dVIiAf4ApbEnkB6qHqsAAAAASUVORK5CYII="): return "9" def get_real_nums(html, none_key): numbers = [] table = Selector(html) fake_css = "img_number " + none_key for num, td in enumerate(table.xpath(".//td")): num_lst = [] position = 0 for img in td.xpath(".//img"): img_src = img.xpath("./@src").get() img_css = img.xpath("./@class").get() if img_css != fake_css: single_num = img_ocr(img_src) offset = img.xpath("./@style").re_first("left:(.+)px") num_lst.append( { "score": float(offset) / 11 + position, "single_num": single_num, } ) position += 1 num_lst = sorted(num_lst, key=lambda x: x["score"]) number = "".join([d["single_num"] for d in num_lst]) numbers.append(number) return numbers
def main(): for page in range(1, 6): num_url = f"http://match.yuanrenxue.com/api/match/4?page={page}" data = requests.get(num_url, headers=yuanrenxue_headers).json() info, key, value = data["info"], data["key"], data["value"] b64 = b64encode((key + value ).encode()).decode().replace("=", "") none_key = hashlib.md5(b64.encode()).hexdigest() print(get_real_nums(info, none_key))
if __name__ == "__main__": main()
|
运行结果