猫眼电影的字体加密还是很折磨人的(最后会附上源码,中间讲解部分就用截图代替)
准备部分
猫眼电影主要在于字体加密,如何破解?需要准备点东西:FontCreator,这是一个软件,下载即可。
开始分析了~,我们以这个为例:https://maoyan.com/films/1209159。
解析字体当然需要当前网页的字体,查看网页源码,找到网页字体 1-1
将字体下载下来,然后刷新页面,会发现字体改变了 1-2
没关系,再下载一次,现在有两个本页面的woff文件 1-3,要进入重点了
分析部分
首先要将下载好的woff文件换个格式 2-1、2-2
将两个保存好的xml文件打开备用 2-3
然后用FontCreator打开我们的两个woff文件 2-4
现在对应关系已经很明了了,我们以4为例:两个woff文件的4分别对应uniE88A、uniE325,然后我们在对应的xml文件中找到它们 2-5、2-6
pt里面的数据是一样,说明我们的字体映射关系找对了,下面就需要设置对应的映射关系了
测试部分
我们先把其中一个woff文件中的对应映射打印出来看一下 3-1、3-2
和我们的xml中的关系对应 3-3
然后我们根据FontCreator中的数据设置对应的映射关系 3-4
输出一下,关系正确 3-5
对应关系已经找到,现在看看网页源码,发现源码中的加密字体都是由&#x开头 3-6
这个不用担心,因为我们只需要把&#x替换成uni就行了,关系就会一一对应,然后就可以返回正确的数据了。
结果
下面开始源码和测试结果
import requests
import re
import os
from fontTools.ttLib import TTFont
class MaoYan():
#初始化需要的数据
def __init__(self):
self.url ='http://maoyan.com/films/1209159'
self.headers = {
"User-Agent":"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36",
}
# 发送请求
def get_html(self, url):
response = requests.get(url,headers=self.headers)
return response.content
#下载woff字体文件
def create_font(self, font_file):
# 列出已下载文件
file_list = os.listdir('./fonts')
# 判断是否已下载
if font_file not in file_list:
# 未下载则下载新woff字体文件
url ='http://vfile.meituan.net/colorstone/' + font_file
new_file =self.get_html(url)
with open('./fonts/' + font_file,'wb')as f:
f.write(new_file)
# 打开字体文件
self.font = TTFont('./fonts/' + font_file)
# 把获取到的数据用字体对应起来,得到真实数据
def modify_data(self, data):
#打开自己保存的woff文件,设置映射关系
font2 = TTFont("./95ebcb3e871c993e8014b6cf244c939b2088.woff")
keys = font2['glyf'].keys()
values =list(' .0714682953')
#对应替换
dict1 =dict((k, v)for k, v in zip(keys, values))
font1 =self.font
#空字典,保存新的替换映射关系
dict2 = {}
for key in font1["glyf"].keys():
for k, v in dict1.items():
# 通过比较 字形定义 填充新的name和num映射关系
if font2["glyf"][k] == font1["glyf"][key]:
dict2[key] = v.strip()
break
#将获取到的网页数据中的&#x替换成uni
for i in dict2:
gly = i.replace('uni','&#x').lower() +';'
if gly in data:
data = data.replace(gly, dict2[i])
return data
#获取数据
def start_crawl(self):
html =self.get_html(self.url).decode('utf-8')
# 正则匹配字体文件
font_file = re.findall(r'vfile\.meituan\.net\/colorstone\/(\w+\.woff)', html)[0]
self.create_font(font_file)
# 正则匹配评分
star = re.findall(r'<span class="index-left info-num ">\s+<span class="stonefont">(.*?)</span>\s+</span>', html)[0]
star =self.modify_data(star)
# 正则匹配想看的人数
people = re.findall(r'<span class=".*?score-num.*?">(.*?)</span>', html,re.S)[0]
people =self.modify_data(people)
# 正则匹配累计票房
ticket_number = re.findall(r'<div class="movie-index-content box">\s+<span class="stonefont">(.*?)</span><span class="unit">(.*?)</span>\s+</div>', html)[0]
ticket_number1 =self.modify_data(ticket_number[0])
print('用户评分: %s' % star)
print('评分人数: %s' % people)
print('累计票房: %s' % ticket_number1,ticket_number[1])
if __name__ =='__main__':
maoyan = MaoYan()
maoyan.start_crawl()
成功结束