Python反反爬系列(二)----破解某点评网站静态字体加密(woff字体映射法)

声明:文章仅源自个人兴趣爱好,不涉及他用,侵权联系删。

1.提醒:

采集之前找好代理,或者限制抓取频率,不然:

2.网站:

    某点评网站,直接说明给链接无法过审,已经审核两次了。。。

3.随便点击一家店铺,查阅评论,顺带检查元素

查看源码:

               

 查看css,定位到字体映射文件:                     

熟悉的woff文件:

                

确定的话直接看开发者工具中的font栏,查看字体文件,如下:  

这。。。一下三个字体,没办法,先查看文件吧,查看可下载可不下载,但是待会儿还是要用,就直接下载了。

查看字体文件:

                 

                

仔细观察源码,字体文件,查找关系,其实和之前是一样的:将unicode编码uni+数字字母==>&#x+数字字母+;:

                    

      结果,相同的字体,不同的编码,但是都是这些汉字和数字,也就是说点评只对这里面的字进行了处理,观察源码的话也是可以看出来的。

      仔细观察刷新会发现,最后相同的字都是处理成同一个格式 。因此,我们只需要构造相应的字典来映射就行了,但是字也不少,7页

                                              

 

5.先用代码抓取评论测试下

def get_source_comment():
    url = "http://www.dianping.com/shop/4209136"
    cookies = "pgv_pvi=2059; pgv_pvid=3615260; RK=uJCEByPxFa; ptcz=06ac16ad51f2024baa375b35912fd658ed9528c10e35cd96f455d871649b94c0; tvfe_boss_uuid=b8ee5f7a8b849d19; LW_uid=W1e514z751r7J4L4P7d0r2o7h3; mobileUV=1_169325cde2e_20678; _ga=GA1.2.708890391.1552552591; gid=3826ef64-e61f-4dc1-b9ab-faec178fa922; ied_qq=o0297299276; pgv_info=ssid=s6566728952; pgv_si=s7773631488; ptisp=ctc; Qs_lvt_311470=1561080189; Qs_pv_311470=3269254339549629400; vfwebqq=5511eeb85f2e02d71b6813b42cb76bd3431e0908054da0616584501c7af8b7764601579aa30106b4; pgg_uid=41108674; pgg_appid=101503919; pgg_openid=DA23561FBBA13B14B9720C5CAA01F496; pgg_access_token=5868BCF1AD63A73299C732A011588932; pgg_type=1; pgg_user_type=5; Qs_lvt_323937=1571207203; Qs_pv_323937=4088341887126509000; LW_sid=9195y7d1v2h0r7A2v0k6a906I5; open_id=DA23561FBBA13B14B9720C5CAA01F496; luin=null; lskey=null; user_id=null; session_id=null; o_cookie=210570136; pac_uid=1_210570136; _qpsvr_localtk=0.371=589796; uid=88761; mpuv=93683705-63df-45b4-cbe1-f32e7ba247bd"
    headers = {
            "Cookie":cookies,
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36"
    }
    proxies = random.choice([
        代理,如果你没有的话记得限速,别请求太快
    ])
    res = requests.get(url=url,headers=headers,proxies = proxies)
    res.encoding = "utf-8"
    with open("1.html","a",encoding="utf-8",errors="ignnore") as f:
        f.write(res.text)
    parse_html = etree.HTML(res.text)
    comment = parse_html.xpath('//p[@class="desc"]//text()')
    for i in comment:
        print(i)

if __name__ == "__main__":
    get_source_comment()

 打印结果:

                    

 所有数据都是请求过来了的,只是有些数据乱码,有些无法显示,从我们保存的文件中,是可以确信数据请求过来了的:

6.获取图片中的所有数字和汉字:

    7页汉字,1个1个输入数量一点多,截图借助图像识别API实现 ,外加人工干预:

识别之前记得修改比例,可以提高识别率:

调整前:

调整后:

识别结果,正确率还可以,稍加修改就可以用了

                                        

嫌麻烦的话,我这边有一份已经好的,需要的留邮箱,将及时发送

                              

必须确保上图数字汉字的字数顺序的正确,因为这个真的很重要,一个错了那么,就会错一大片

上图的饕餮两字,如果你问我为什么会出现这两个字,说明你还没懂字体破解的方法。

7.思路分析:

    1.确认三个字体文件:1个是首次店铺信息的加密字体文件,1个是评论的字体文件,还有1个,那么需要抓哪部分信息就针对某个特定的字体文件进行分析;

    2.获取网页,获取response.text如果有需要可以,保存为html

    3.获取网页同时保存字体文件,借助上数字汉字字体库,构造相应的字典

    4.借助字典映射替换unicode编码文字;

    5.获取店铺信息+店铺评论信息等

下面按照思路逐步进行。

8.保存字体文件和相应的文本文件

def saveHtml_saveWoff():#保存相应的html 和 此次的woff字体
    url = "http://www.dianping.com/shop/659275097"
    cookies = "你的cookies"
    headers = {
            "Cookie":cookies,
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36"
    }
    proxies = random.choice([
       #代理

    ])
    res = requests.get(url=url,headers=headers,proxies = proxies)
    res.encoding = "utf-8"
    with open("1.html","a",encoding="utf-8",errors="ignnore") as f:
        f.write(res.text)

    #先抓取css,找到woff文件链接,保存字体
    css_href_list = re.findall(r'href="(//s3plus\.meituan\.net/v1.{,100}?)"',res.text,re.S)
    if css_href_list:
        # "http://s3plus.meituan.net/v1/mss_0a06a471f9514fc79c981b5466f56b91/svgtextcss/5a0bcb14e31bbc0da33526d05daa8a2d.css"
        css_href = "http:" + css_href_list[0]
        text = requests.get(css_href).text
        print(text)
        woff_url = re.findall(r'(//s3plus\.meituan\.net/.{,100}?woff)',text)[0]
        print("http:"+woff_url)
        content = requests.get("http:"+woff_url).content

        with open("target.woff","wb") as f:
            f.write(content)

9.将字符 和 编码建立对照表

def get_font_map():
    font = TTFont("./target.woff")
    # fontMap = font.getBestCmap() #getBestCmap()返回cmap表中对应的映射,只不过code字段返回的为十进制数据,如果想转为十六进制,使用hex()内置方法即可
    # print(fontMap)
    font_names = font.getGlyphOrder() #getGlyphOrder()方法返回所有字符编码名称,按表格顺序提取,类型为列表
    print(font_names)

    texts = list('''将字体库中的所有汉字复制上来'''.replace(" ","").replace("\n","").replace("\r","").replace("\t",""))

    print('字体编码名称数量:', len(font_names))
    print('字体编码对应解码字符数量:', len(texts))

    num_uni_dict = {}
    for i, uni in enumerate(font_names):
        num_uni_dict[uni.lower().replace('uni', '&#x') + ';'] = str(texts[i])
    print("字体映射字典",num_uni_dict)
    return num_uni_dict

10.借助映射表,将网页中的特殊格式字符替换,获取数据:

def get_info():
    with open("./1.html","r",encoding="utf-8",errors="ignore") as f:
        html = f.read()
        # print(html)

    map_dict = get_font_map()
    for uni in map_dict.keys():
        html = html.replace(uni, map_dict[uni])

    parse_html = etree.HTML(html)

    li_list = parse_html.xpath('//div[@id="comment"]//ul//li')
    for li in li_list[0:10]:#我们只要取前10个,其他都是重复的
        user_name = li.xpath('./p[@class="user-info"]//a[@class="name"]//text()')
        comment = li.xpath('./div[@class="content"]//p[@class="desc"]//text()')
        print("用户名:",user_name[0],"  评论:","".join(comment))

最终实现效果:

可以和处理前的评论对比下:

参考:

https://blog.csdn.net/qq_36853469/article/details/103701048

https://www.jianshu.com/p/cc3dee3b5373

发布了128 篇原创文章 · 获赞 95 · 访问量 35万+

猜你喜欢

转载自blog.csdn.net/qq_36853469/article/details/103701048