众所周知,社区是需要邀请注册的,也就是聚聚生成邀请码,来分享给未注册的朋友使用。但是很多时候,聚聚分享出来的邀请码都是带有掩码的,
例如 abcde*abc*a*a*12 这种形式。同时,星号 * 可能代表任意字母或数字。
引用
感谢 聚聚@夜游宫 提醒
字母只会是abcdef中的,其他20个字母不会出现在邀请码里面的。(新人朋友一定要知道这一点,不然尝试隐藏邀请码时,会浪费时间做很多无用功)
接下来,我们尝试通过代码来揭示掩码背后可能存在的真实邀请码。
首先,让我们进行简单的分析。任意的字母或数字可以表示为 "abcdef0123456789" ,长度为 16。
假设有 4 位掩码,共有 16x16x16x16 = 65,536 种组合。
聪明的朋友可能会想到使用递归来遍历每一位来生成真实邀请码,具体实现如下:
- str_mask = "cp2iv*qpz*y*q*12"
- def generate_real_codes():
- real_codes = []
- mask_length = len(str_mask)
- def generate_codes_helper(current_code, index):
- if index == mask_length:
- real_codes.append(current_code)
- return
- if str_mask[index] == '*':
- for char in "abcdef0123456789":
- generate_codes_helper(current_code + char, index + 1)
- else:
- generate_codes_helper(current_code + str_mask[index], index + 1)
- generate_codes_helper('', 0)
- print(len(real_codes)) # 输出:65,536
- return real_codes
然后,我们可以进一步优化。下面是一个更高效的方法:
- from itertools import product
- def generate_real_codes_v2():
- real_codes = []
- possible_chars = []
- for ch in str_mask:
- if ch == '*':
- possible_chars.append("abcdef0123456789")
- else:
- possible_chars.append(ch)
- for code in product(*possible_chars):
- real_codes.append(''.join(code))
- print(len(real_codes)) # 输出:65,536
- return real_codes
可以看到,这段改进后的代码速度提高了一倍。改进后的代码之所以更高效,主要有以下几个原因:
1. 使用了 itertools.product 函数:在改进后的代码中,我们利用了 itertools.product() 函数,它能够生成多个可迭代对象的笛卡尔积,避免了嵌套循环的使用,简化了代码结构,提高了性能。
2. 减少了字符串拼接次数:将字符串拼接操作集中在生成完所有解码结果后进行,减少了字符串拼接的次数,提高了效率。
综上所述,通过优化字符集构建、使用 itertools.product() 函数以及减少字符串拼接次数,改进后的代码在生成所有实际邀请码的过程中更加高效。这使得我们能够更快地处理包含多种掩码规则的字符串,节省时间和资源。
然而,还有一个问题需要解决。
因为有些同学可能比较皮, 掩码很个性, 比如这种 “cp2iv★qpz★y★q*12”
而且这个同学还说 ★ 是随机数字, 而 * 是随机字母+数字.
因为我们脚本需要稍作优化.需要把具体的匹配规则抽出来, 当成可以配置变更的,如下:
- mask_rule = {
- '*': "abcdef0123456789",
- '★': "0123456789",
- }
- def generate_real_codes_v2_plu():
- invite_codes = []
- possible_chars = []
- for ch in str_mask:
- if ch in list(mask_rule.keys()):
- possible_chars.append(mask_rule.get(ch))
- else:
- possible_chars.append(ch)
- for code in product(*possible_chars):
- invite_codes.append(''.join(code))
- return invite_codes
至此,看似写完了, 然而,还有一个问题需要解决。如果掩码的位数足够大,生成的邀请码数量也会非常庞大,将它们全部存储在列表中可能会消耗大量内存。
为了避免这个问题,我们可以使用生成器(generator),逐个生成邀请码,而不是一次性生成所有代码并存储在内存中。这就像是一种懒加载的方式。
下面是使用生成器进行优化的代码:
- def generate_real_codes_v2_plu_plu():
- possible_chars = []
- for ch in str_mask:
- if ch in mask_rule:
- possible_chars.append(mask_rule[ch])
- else:
- possible_chars.append(ch)
- for code in product(*possible_chars):
- yield ''.join(code)
生成器对象本身并不直接支持获取长度,因为生成器是一种惰性计算的机制,它并不实际生成所有的元素。
所以可以直接用掩码位数与每个掩码可能出现的字符数的乘积来计算结果
16x16x16x16 = 65,536
至此,我们的代码基本完成了优化和修复。
最后: 祝各位看帖的新人,早日上岸~!
[ 此貼被爱自由在2023-08-11 18:12重新編輯 ]
赞(30)