猫眼字体反爬虫

 我在这里不直接瞎bb, 只提供代码。 因为好多人写的都很棒, 我在这里面提供链接,想看的童鞋可以去看, 一步步跟别人走就能 get 到你想要的。 大佬链接:

https://blog.csdn.net/xing851483876/article/details/82928607

https://blog.csdn.net/weixin_42812527/article/details/86548948\

其实我的代码也是偷的, 只不过稍微修改了下, 嘻嘻嘻,主要是会了就行, 别人的东西学会了就是自己的。

import re
import base64
import chardet
import requests
from scrapy import Selector
from fontTools.ttLib import TTFont


url = 'https://piaofang.maoyan.com/?ver=normal'
headers = {
    "User-Agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36",
}
response = requests.get(url=url, headers=headers)
coding = chardet.detect(response.content).get('encoding', 'utf-8')    # 得到编码格式
response = str(response.content, encoding=coding, errors='ignore')    # 解码得到字符串

# 第一次获取的字体,以及对应编码位置,需要手动写一次。  getGlyphNames()  和  getGlyphOrder()  这个是有用的
origin_fonts = TTFont('online_base64.ttf')
origin_obj_list1 = origin_fonts.getGlyphNames()[1:-1]  # 获取所有字符的对象,去除第一个和最后一个,之前的图已经解释清楚为什么去掉最后一个和第一个。
origin_uni_list1 = origin_fonts.getGlyphOrder()[2:]    # 获取所有编码,去除前2个。
# origin_dict = {'uniF855': '1', 'uniF755': '8', 'uniF617': '9', 'uniE4CA': '4', 'uniE912': '6', 'uniF514': '3',
#                'uniE3A5': '7', 'uniF594': '5', 'uniF16A': '0', 'uniF09C': '2'}

# 写出第一次字体文件的编码和对应字体。
origin_dict = {'uniE08C': '8', 'uniE8F5': '2', 'uniEF9B': '1', 'uniEDD2': '9', 'uniEDA2': '3', 'uniF294': '4', 'uniF7F6': '0',
                'uniE352': '7', 'uniF357': '5', 'uniE35B': '6'}

# 获取字体文件的base64编码
online_ttf_base64 = re.findall(r"base64,(.*)\) format", response)[0]
print(online_ttf_base64)
online_base64_info = base64.b64decode(online_ttf_base64)
with open('new_online_base64.ttf', 'wb')as f:
    f.write(online_base64_info)
online_base64_fonts = TTFont('new_online_base64.ttf')  # 网上动态下载的字体文件。
online_obj_list2 = online_base64_fonts.getGlyphNames()[1:-1]  # 同上。
online_uni_list2 = online_base64_fonts.getGlyphOrder()[2:]


# 第一个 和 第二个进行对比, 得到的对象相同说明是相同的数字, 然后再替换一下得到的字符串。
# 接着就相当于获取得到了相同的对象, 根据第一个获取到的字典, 动态变化生成第二个。
# 下面的这个demo 是死的, 直接复制粘贴就行
for uni2 in online_uni_list2:
    obj2 = online_base64_fonts['glyf'][uni2]  # 获取编码uni2在online_base64.ttf中对应的对象
    for uni1 in origin_uni_list1:
        obj1 = origin_fonts['glyf'][uni1]  # 获取编码uni1在origin.ttf 中对应的对象。
        if obj1 == obj2:  # 如果对象一等于对象二
            dd = "&#x" + uni2[3:].lower() + ';'  # 把编码uni2替换成Unicode编码格式。
            if dd in response:  # 如果编码uni2的Unicode编码格式在response中,那么替换成origin_dict[uni1]的字体。
                response = response.replace(dd, origin_dict[uni1])

response_info = Selector(text=response)
all_info = response_info.xpath('//ul[@class="canTouch"]')  # 获取所有的信息
print(len(all_info))
exit()
print('电影名字' + '\t' + '实时票房(万元)' + '\t' + '票房占比' + '\t' + '排片占比' + '\t' + '上座率')
for each_info in all_info:
    # 这个一行一行的取数据, 也可以。  因为这个是规则的, 也可以一列一列的取, 一一对应就行了
    # extract_first()  相当于  extract()[0] 意思是一样的
    movie_name = each_info.xpath('li[1]/b/text()').extract_first()  # 电影名字
    ticket_number = each_info.xpath('li[2]/b/i[@class="cs"]/text()').extract_first()  # 实时票房(万元)
    ticket_rate = each_info.xpath('li[3]/i[@class="cs"]/text()').extract_first()  # 票房占比
    film_rate = each_info.xpath('li[4]/i[@class="cs"]/text()').extract_first()  # 排片占比
    upper_seat_rate = each_info.xpath('li[5]/span/i[@class="cs"]/text()').extract_first()  # 上座率
    print(movie_name + '\t' + ticket_number + '\t' + ticket_rate + '\t' + film_rate + '\t' + upper_seat_rate)

 下面是我自己写的代码, 但是感觉我写的很复杂啊, 代码这么多, 注意点就是,  先请求获取第一次的 ttf , 写好字典映射对象,然后接着写下面的脚本就行了,这个代码目前是可以直接用的

import re
import base64
import requests
from lxml import etree
from fontTools.ttLib import TTFont    # 安装 fontTools,应该是直接  pip install fonttools 就可以


def index():
    url = "https://piaofang.maoyan.com/?ver=normal"
    headers ={
            'Cookie':'_lxsdk_cuid=16b69593cb4c8-0a7953d21b37a4-3b65410e-1fa400-16b69593cb4c8; _lxsdk=16b69593cb4c8-0a7953d21b37a4-3b65410e-1fa400-16b69593cb4c8; theme=moviepro; _lxsdk_s=16b69593cb5-8af-950-391%7C%7C6',
            'Host':'piaofang.maoyan.com',
            'Referer':'https://blog.csdn.net/xing851483876/article/details/82928607',
            'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36',
    }
    response = requests.get(url=url, headers=headers)
    content = response.text
    # 获取font_face 对应的ttf文件
    font_face = re.findall(r"base64,(.+?)\) format",content)[0]
    print("font_face:", font_face)

    # 替换之后的文本信息
    contents = get_ttf_xml(font_face, content)
    html = etree.HTML(contents)
    # 电影名称
    movie_name = html.xpath("//div[@id='ticket_tbody']/ul[@class='canTouch']/li[@class='c1']/b/text()")
    print("movie_name:", movie_name)
    print(len(movie_name))
    # 实时票房
    shishihouse = html.xpath("//div[@id='ticket_tbody']/ul[@class='canTouch']/li[@class='c2 ']//i[@class='cs']/text()")
    print("实时票房:", shishihouse)
    print(len(shishihouse))
    # 排片占比
    paipian = html.xpath("//div[@id='ticket_tbody']/ul[@class='canTouch']/li[@class='c4']/i[@class='cs']/text()|//div[@id='ticket_tbody']/ul[@class='canTouch']/li[@class='c4 ']/i[@class='cs']/text()")
    print("排片占比:", paipian)
    print(len(paipian))
    # 票房占比
    zhanbi = html.xpath("//div[@id='ticket_tbody']/ul[@class='canTouch']/li[@class='c3 ']/i[@class='cs']/text()")
    print("票房占比:", zhanbi)
    print(len(zhanbi))
    # 上座率
    shangzuo = html.xpath("//div[@id='ticket_tbody']/ul[@class='canTouch']/li[@class='c5']/span[1]/i[@class='cs']/text() |//div[@id='ticket_tbody']/ul[@class='canTouch']/li[@class='c5 ']/span[1]/i[@class='cs']/text()")
    print("上座率:", shangzuo)
    print(len(shangzuo))


def get_ttf_xml(font_face, content):
    """ 获取ttf文件, 转化成xml格式"""
    b = base64.b64decode(font_face)
    with open('zt02.ttf', 'wb')as f:
        f.write(b)
    font = TTFont('zt02.ttf')  # 打开本地字体文件01.ttf
    font.saveXML('zt02.xml')   # 将ttf文件转化成xml格式并保存到本地,主要是方便我们查看内部数据结构
    online_base64_font2 = TTFont('zt02.ttf')  # 打开本地字体文件02.ttf
    online_obj_list2 = online_base64_font2.getGlyphNames()[1:-1]  # 获取所有字符的对象,去除第一个和最后一个    坐标
    online_uni_list2 = online_base64_font2.getGlyphOrder()[2:]    # 获取所有编码,去除前2个
    print("第二次字符对象online_obj_list2:", online_obj_list2)
    print("第二次字符编码online_uni_list2:", online_uni_list2)
    # 两次信息比对, 找到对象相等字符, 然后根据第一个字符对象字典 去 映射值
    for uni2 in online_uni_list2:
        obj2 = online_base64_font2['glyf'][uni2]  # 获取编码uni2在online_base64.ttf中对应的对象
        for uni1 in origin_uni_list1:
            obj1 = origin_fonts['glyf'][uni1]  # 获取编码uni1在origin.ttf 中对应的对象。
            if obj1 == obj2:  # 如果对象一等于对象二
                """ .   加密的数字 """
                dd = "&#x" + uni2[3:].lower() + ';'  # 把编码uni2替换成Unicode编码格式。
                # print("dd", dd)
                if dd in content:  # 如果编码uni2的Unicode编码格式在response中,那么替换成origin_dict[uni1]的字体。
                    content = content.replace(dd, origin_dict[uni1])
    return content


if __name__ == '__main__':
    # 第一次获取的字体,以及对应编码位置,需要手动写一次,  因为这个猫眼的字体对应是一直变化的, 你不可能一直实时替换,这么写是一种通用的写法, 手动写一次, 然后第二次获取的ttf 文件自己去比对数据结构
    # 根据字符的结构来确定字体,  字符编码变化都无所谓了, 通过第一次的比对映射过来真实的数字就行了   1 - > 2 -- >1 --> 得到数字
    origin_fonts = TTFont('zt01.ttf')
    origin_obj_list1 = origin_fonts.getGlyphNames()[1:-1]  # 获取所有字符的对象,去除第一个和最后一个,之前的图已经解释清楚为什么去掉最后一个和第一个。
    origin_uni_list1 = origin_fonts.getGlyphOrder()[2:]  # 获取所有编码,去除前2个。
    origin_dict = {'uniEFFF': '1', 'uniE161': '8', 'uniE874': '9', 'uniF864': '4', 'uniEB3A': '6', 'uniF4C3': '3','uniF624': '7', 'uniEB1E': '5', 'uniE584': '0', 'uniF357': '2'}  # 写出第一次字体文件的编码和对应字体。
    print("---所有字符的对象--- origin_obj_list1:", origin_obj_list1)
    print("---所有字符的编码--- origin_uni_list1:", origin_uni_list1)
    index()

下面自己请求一下就出来了, 我弄着玩的, 保留一份源码

# 自己复制下来命名一下 zt_01.ttf

wOFF     $     ?                      GSUB     3   B剥稠OS/2  <   D   VV頦踓map  €   ? LO晚glyf  @  ? 4椷head  ?  /   6撝^hhea        $?9hmtx         0  loca  4      ddmaxp  P        Hk岯齏9鹱鮨??\$?\)!.?彵椑厁(4榘郪淚酶GK2潋l??逅邑-#j躿惌}ij椮??迉(谊儓盠廠ⅹ辱蛫sH€$R>HX{B?说?╥?k迱蛻X熄椰L$薎qJ?樊滯k!W9鄕?L?檛n?涷灘n.竾/.砈3e`]-?€
@+??塪Hn?跷甙p毖ň{V倗◆?:7w|勬zy 棇?炄s?w@傄U'?qk你m-铴?漹氰碘u璓+輄嶐B把瀇.oD糙蚅揫^澂緕~gnR畯油?本K茹4渷2g臡;P顠hz覥錪?挔?儦Iq+=瘪穎鞔暂??豘橬U聭{胚4e,瓁昭丼謭pw?稛黚L?榋\?卵5p掿鈉Gn1#?菰%竁
带归Q~0?>蚷E廆澨|@3! 艸ye1G詞膇(鯹肣撪?7h?l睭?刺"瑵?絆G	]郋険乺亠竽bJ@?7}mn綻k挢5&朌*糜gā搢:3 ?:?枆A欰箋n!锖鮮S愯鯫1鴵?蓱@劜6さ冧哲?孃啰?O?珫妛藰[ζ(廛?5賜陊f~~qX_&藵W鉌炊4稸関?;咠i钉唏瀓M襵煁?J顊蹨毉V舁N嵴蝱.0嗽%騙n亭^鎠[O+w?俯G?/??`j嗦 x渃`d`` b沖蓠顸6_竃@唳昰0傼唴侀<愃晾 R	?x渃`d``柱寐 @拺? 3b蛒渃a ?&? 7?5        R v ??Pj??  x渃`d``郺0``f & ?B?`> ?V x渆懟n翤D??)B墧&姶M?藽㏄:$(#Q??#看^怘?葁?谣?は`??餅;3w}%钙7湠{?vp陵?溿A窷齀窤~n???簒n?o剂i\?鉉谹熉5\酜窷鼼窤?n庵i
煛丬	钒p郝m<:??F{V驙???&詥N瑙蒕氹?騆Y栫B?L5t?訅6錷鶁=?P両c5カ?U橧汾奉期l茱⒒~s

#自己复制下来命名一下  zt01.xml




  
    
    
    
    
    
    
    
    
    
    
    
    
    
  

  
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
  

  
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
  

  
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
  

  
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
      
      
      
      
      
      
      
      
      
      
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
  

  
    
    
    
    
    
    
    
    
    
    
    
    
  

  
    
    
      
      
      
      
      
      
      
      
      
      
      
    
    
      
      
      
      
      
      
      
      
      
      
      
    
    
      
    
    
      
      
      
      
      
      
      
      
      
      
      
    
    
      
      
      
      
      
      
      
      
      
      
      
    
  

  
    
  

  

    

    

    
      
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
      
      
        
        
        
        
        
        
        
        
        
        
        
      
      
        
        
        
        
        
        
        
        
        
        
        
        
        
        
      
      
    

    
      
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
      
      
        
        
        
        
        
        
        
        
        
        
        
      
      
    

    
      
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
      
      
        
        
        
        
        
        
        
        
        
        
        
        
      
      
    

    
      
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
      
      
    

    
      
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
      
      
        
        
        
        
        
        
        
        
        
        
        
        
      
      
    

    
      
        
        
        
        
        
        
        
        
        
        
        
        
        
      
      
    

    
      
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
      
      
    

    
      
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
      
      
    

    
      
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
      
      
    

    
      
        
        
        
        
        
        
        
        
        
        
        
      
      
        
        
        
      
      
    

    
      
        
        
        
      
      
    

  

  
    
      
  Created by font-carrier
  
    
    
      iconfont
    
    
      Regular
    
    
      iconfont
    
    
      iconfont
    
    
      Version 1.0
    
    
      iconfont
    
    
      Generated by svg2ttf from Fontello project.
    
    
      http://fontello.com
    
    
      
  Created by font-carrier
  
    
    
      iconfont
    
    
      Regular
    
    
      iconfont
    
    
      iconfont
    
    
      Version 1.0
    
    
      iconfont
    
    
      Generated by svg2ttf from Fontello project.
    
    
      http://fontello.com
    
  

  
    
    
    
    
    
    
    
    
    
    
      
      
    
    
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
    
  

  
    
    
      
      
        
        
      
    
    
      
      
        
        
          
          
        
      
    
    
      
      
        
        
        
        
        
      
    
  


 

你可能感兴趣的:(python爬虫加密)