字體文件反爬
在搞定靜態(tài)字庫反爬之后蝗羊, 可以解決部分字體文件的反爬框杜, 但動(dòng)態(tài)字文件反爬是解決不掉的咪辱。此文章就是為解決動(dòng)態(tài)字體文件的反反爬而寫弱贼。本想以去哪兒網(wǎng)(手機(jī)端)的為例, 奈何手機(jī)端的字庫反爬可能需要賬號(hào)密碼才會(huì)出現(xiàn)仁堪, 遂改用貓眼電影網(wǎng)的字體文件反爬為例哮洽。源碼在最后!
1. 開發(fā)者模式查看網(wǎng)頁內(nèi)容
2. 下載網(wǎng)頁源碼保存至本地查看
3. 字體文件保存在本地通過 font creator
查看字體文件信息
可以查看到字體文件的映射關(guān)系是動(dòng)態(tài)的弦聂, 需要解決的就是通過某種方法來找到映射與數(shù)字之間的關(guān)系鸟辅。
4.通過fontTools庫氛什, 將字庫文件轉(zhuǎn)換成xml格式
# 將字體文件轉(zhuǎn)換成xml格式可以發(fā)現(xiàn)字體保存的圖行信息是不變的, 變化的是unicode映射
#以此為突破點(diǎn)匪凉, 找到圖形對(duì)應(yīng)的編碼枪眉, 然后再匹配到對(duì)應(yīng)的數(shù)字,以不變應(yīng)萬變再层。
onlineFonts = TTFont('fonts.woff')
onlineFonts.saveXML('test.xml')
注: 此步驟在實(shí)際生產(chǎn)過程中并不需要贸铜, 為了便于理解, 我加上了
5.通過fontTools庫聂受, 獲取字體信息中不變的部分
baseFonts = TTFont('basefonts.woff') # basefonts.woff 這個(gè)文件是保存在本地的蒿秦, 需要手動(dòng)解析一個(gè)字體庫, 作為不變的部分
base_nums = ['7', '9', '0', '3', '6', '5', '2', '1', '4', '8'] # 基本的數(shù)字表
base_fonts = ['uniF04C', 'uniE374', 'uniF426', 'uniEAAA', 'uniF519', 'uniEEC4', 'uniF543', 'uniF7C7', 'uniF046',
'uniF08E'] # 基本的映射表
onlineFonts = TTFont('fonts.woff') # 網(wǎng)絡(luò)上下載的動(dòng)態(tài)的字體文件
uni_list = onlineFonts.getGlyphNames()[1:-1] # 只有中間的部分是數(shù)字
temp = {}
# 解析字體庫
for i in range(10):
onlineGlyph = onlineFonts['glyf'][uni_list[i]] # 返回的是unicode對(duì)應(yīng)信息的對(duì)象
for j in range(10):
baseGlyph = baseFonts['glyf'][base_fonts[j]]
if onlineGlyph == baseGlyph:
temp["&#x" + uni_list[i][3:].lower() + ';'] = base_nums[j]
6.最終結(jié)果展示
參考資料:
知乎作者謝俊杰的文章
fontTools庫詳解
github fonttools庫詳解
本人水平有限蛋济, 如有錯(cuò)誤歡迎提出指正棍鳖!如有參考, 請(qǐng)注明出處M肼谩渡处!禁止抄襲,遇抄必肛K畋佟R教薄!
源碼:
# coding:utf-8
import re
import requests
from fontTools.ttLib import TTFont
from lxml import etree
headers = {
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/66.0.3359.139 Safari/537.36 "
}
index_url = 'http://maoyan.com/'
# 獲取首頁內(nèi)容
response_index = requests.get(index_url, headers=headers).text
index_xml = etree.HTML(response_index)
info_list = index_xml.xpath('//*[@id="app"]/div/div[1]/div[1]/div/div[2]/ul/li[1]/a/div[2]/div//text()')
a = u'電影名稱:%s, 票房總數(shù):%s' % (info_list[1], info_list[4])
print (a)
# 獲取字體文件的url
woff_ = re.search(r"url\('(.*\.woff)'\)", response_index).group(1)
woff_url = 'http:' + woff_
response_woff = requests.get(woff_url, headers=headers).content
with open('fonts.woff', 'wb') as f:
f.write(response_woff)
#base_nums旧困, base_fonts 需要自己手動(dòng)解析映射關(guān)系醇份, 要和basefonts.woff一致
baseFonts = TTFont('basefonts.woff')
base_nums = ['7', '9', '0', '3', '6', '5', '2', '1', '4', '8']
base_fonts = ['uniF04C', 'uniE374', 'uniF426', 'uniEAAA', 'uniF519', 'uniEEC4', 'uniF543', 'uniF7C7', 'uniF046',
'uniF08E']
onlineFonts = TTFont('fonts.woff')
# onlineFonts.saveXML('test.xml')
uni_list = onlineFonts.getGlyphNames()[1:-1]
temp = {}
# 解析字體庫
for i in range(10):
onlineGlyph = onlineFonts['glyf'][uni_list[i]]
for j in range(10):
baseGlyph = baseFonts['glyf'][base_fonts[j]]
if onlineGlyph == baseGlyph:
temp["&#x" + uni_list[i][3:].lower() + ';'] = base_nums[j]
# 字符替換
pat = '(' + '|'.join(temp.keys()) + ')'
response_index = re.sub(pat, lambda x: temp[x.group()], response_index)
# 內(nèi)容提取
index_xml = etree.HTML(response_index)
info_list = index_xml.xpath('//*[@id="app"]/div/div[1]/div[1] /div/div[2]/ul/li[1]/a/div[2]/div//text()')
a = u'電影名稱:%s, 票房總數(shù):%s' % (info_list[1], info_list[4])
print(a)