背景介绍

【验证码开放平台】 - 通过我们的 API 服务和终极一站式解决方案,赋能开发者构建强大的网络爬虫与数据采集项目。

进入正题

这两天跟一个文字点选验证码杠上了,就那种给你一堆乱序的图,让你按顺序点文字的。

问题不大,先得把图给拼回来。官方的玩法是,根据一个captcha_id,生成一个乱序映射的数组,然后按这个数组把切碎的图重新排一遍。

生成那个数组的逻辑,一开始看还有点绕,其实就是把id里的每个字符转成ASCII码,然后对32取模,如果模数冲突了就往后顺延,保证不重复。代码很短,几行搞定:

def get_image_arry(r):
    t = []
    for e in [ord(i) for i in r]:
        while e % 32 in t:
            e += 1
        t.append(e % 32)
    return t

有了这个数组,就相当于有了“图纸”。接下来就是拼图。

这里我踩了个坑,对着“图纸”拼的时候,脑子抽了,把原图的列和要放的位置弄反了。结果拼出来的图,不是字碎了,就是脸歪了,反正人是看不懂的。后来才反应过来,人家告诉你的意思是“乱序图里第c列,应该放在正常图的第xp列”,我给搞成反向映射了。修正之后,图就正常了。拼图代码大概长这样,可以直接用:

def img_recover(self,binary, captcha_id):
    # 先拿到还原顺序的数组,restore_list 就是上面那个函数生成的
    restore_list = self.get_image_arry(captcha_id) 
    img = cv2.imdecode(np.array(bytearray(binary), dtype='uint8'), cv2.IMREAD_UNCHANGED)
    new_img = np.zeros((150, 288, 3), dtype=np.uint8)
    lk = len(restore_list)
    ck = int(300 / lk)
    for cp in range(lk):
        c = restore_list[cp] % lk * ck
        xp = cp % lk * ck
        slice_img = img[0: 150, c: c + ck]
        new_img[0: 150, xp:xp + len(slice_img[0])] = slice_img
    new_img = cv2.resize(new_img, (300, 150)) 
    normal_img = cv2.imencode('.jpg', new_img)[1]
    normal_img = np.array(normal_img).tobytes()
    return normal_img

图拼好了,我以为最难的部分过去了,结果噩梦才刚开始——那个叫ac的加密参数。

一开始我生成的ac,长度才153。真的,就153个字符。然后奇葩的是,在某些站点,这么短的玩意儿,它竟然也能过!那种感觉就像你去面试,穿个拖鞋大裤衩,结果面试官还给你发offer了,离谱。

但碰到像海航那种比较严格的站点,直接就给我踹回来了,死活过不去。因为原版官方的ac,长度是一千多啊……

这明显是greenseer里面缺浏览器环境,很多东西没补上。没办法,缺啥补啥呗,打补丁的日子就这么开始了。

补屏幕分辨率、补Canvas指纹、补WebGL、补字体列表、补插件……各种补。真的是缝缝补补又一年。中间好几次想直接摆烂,不干了,一想到“兄弟,你这个ac太短了”的嘲讽,就又咬着牙继续加。

最后,终于把长度从153,怼到了900多。虽然跟官方的1000多还差那么一百来字节,但实测下来,基本能通用了。当我看到那个请求终于返回200,验证通过的绿勾出现时,心里只有一句话:这玩意儿,真的不能太短,太短了真会被看不起。

最后,关于constidac的生成逻辑,之前的文章里都写过,直接搬过来改改参数就能用。

总结

这篇文章其实也没啥高深的,就是记录一下。希望兄弟们少走点弯路,尤其是那个拼图顺序的坑和ac长度的坑,一定要注意。

【验证码开放平台】 - 通过我们的 API 服务和终极一站式解决方案,赋能开发者构建强大的网络爬虫与数据采集项目。

Logo

免费领 150 小时云算力,进群参与显卡、AI PC 幸运抽奖

更多推荐