春節假期剛過,大家有沒有看春節檔的電影呢?今年的春節檔電影很是火爆,我們可以在貓眼票房app檢視有關資料,因為資料一致在更新,所以他的字型是動態的,想要爬取有些困難,再加上貓眼app對字型進行加密,該如何爬取呢?本文介紹反爬2021貓眼票房字型加密的例項。
一、字型加密原理簡單來說就是程式設計師在設計網站的時候使用了自己設計的字型程式碼對關鍵字進行編碼,在瀏覽器載入的時會根據這個字型檔案對這些字型進行編碼,從而顯示出正確的字型。
二、爬取例項1、得到字型斜率字典
1 2 3 4 5 6 7 8 9 10 11 12 13 |
import requestsimport urllib.request as downimport jsonfrom fontTools.ttLib import TTFontimport reimport MyPyClass# 得到字型斜率列表(部分)def font_Kdict(mapstype,maps=None): ''' 得到字型斜率字典(部分) 引數: mapstype:str->maps型別,判斷是是base/new maps:對映字典 return kdict kdict字典關係: num:Klist 數字對應每條線段的斜率列表 ''' kdict={} |
2、遍歷maps字典,找到對應的num和namecode
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
for num, namecode in maps.items(): # 跳過無用資料 if namecode == 'x': continue # 判斷型別,並從.coordinates得到對應num的所有座標 if mapstype=='base':coordinates = namecode.coordinates elif mapstype=='new':coordinates=glyf[namecode].coordinates # 得到座標 X列表和座標 Y列表 x = [i[0] for i in coordinates] y = [i[1] for i in coordinates] Klist = [] # 遍歷X列表並切片為前10個數據進行斜率計算,即代表繪圖的前10條線段的斜率 for index, absx in enumerate(x[:10]): # 當斜率為0/1時,認為斜率為1計算 if x[index + 1] == x[index] or y[index + 1] == y[index]: absxy = 1 else: absxy = (y[index + 1] - y[index]) / (x[index + 1] - x[index]) # 將斜率加入到列表 Klist.append(-absxy if absxy < 0 else absxy) kdict[num]=Klist #print('base:', code, Klist, name) return kdict |
3、對比斜率字典
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
def contrast_K(kbase,knew): ''' 對比斜率對映差距 引數: kbase:基礎字型對映表的斜率字典 knew:當前連結的字型對映表的斜率字典 return:dict fontMaps:根據對比得出正確的字型對映關係字典 fontMaps = {} # 遍歷kbase字典 for base in kbase.items(): n = 0 # 成功匹配的斜率個數 # 遍歷knew字典 for new in knew.items(): # 遍歷kbase>knew>下的兩組斜率,進行大小匹配, # 如果斜率k的差值小於0.5,並且樣本數>=9時,認為兩個座標圖形相識只是大小比例不同 # 即k<=0.5 n>=9 for (k1,k2) in zip(base[1],new[1]): # k取正數 k=k1-k2 if k1>k2 else k2-k1 if k<=0.5: n+=1 continue else: break if n>=9: # 匹配正確則新增進字典中 此時的字典關係是:code:num 程式碼對應數字的關係 fontMaps[str(hex(new[0]).replace('0x',''))]=str(base[0]) break n=0 #print(fontMaps) return fontMaps |
4、爬取內容
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
with requests.get(url,headers={'user-agent':ua}) as response: # 獲取存放字典的json欄位,並提取字型url fontStyle=json.loads(response.content)['fontStyle'] fontStyle=re.findall('\"([\s\S]*?)\"',fontStyle[::-1]) fonturl='http:'+fontStyle[0][::-1]# 字型url連結 # 將載入的字型下載儲存到本地,並對其進行分析 down.urlretrieve(fonturl,'newfont.woff') # 爬取的電影資料內容 content = json.loads(response.content)['movieList']['data']['list']# 資訊字典movieNum={}#綜合票房數字典movieDayOne= {}#上映首日數量movieRate={}#票房佔比movieshowCount={}#排片場次movieViewerAvg={}#場均人數movieInfos={}# 頁面內容for i in content: moviename=i['movieInfo']['movieName'] movieNum[moviename]=i['boxSplitUnit']['num'] movieDayOne[moviename]=i['sumBoxDesc'] movieRate[moviename]=i['splitBoxRate'] movieshowCount[moviename]=i['showCount'] movieViewerAvg[moviename]=i['avgShowView']# 新字型物件fontnew=TTFont('newfont.woff') # 得到當前字型的對映關係表newNumberMaps=fontnew.getBestCmap()# 獲取字形glyf=fontnew['glyf'] # 基礎字型斜率字典k_base_dict=font_Kdict(maps=baseNumberMaps,mapstype='base') # 新字型斜率字典k_new_dict=font_Kdict(maps=fontnew.getBestCmap(),mapstype='new') # 得到字型對映字典fontcodes=contrast_K(k_base_dict,k_new_dict)# 對加密的字型遍歷分組,並去除無用字元 for name,numbercode in movieNum.items(): movieNum[name]=re.findall('([\S]*?);', numbercode) # 根據得到的fontcodes對映對加密字型進行替換,得到正確數值for index,(name,numbercodelist) in enumerate(movieNum.items()): num=[] # 替換操作 for code in numbercodelist: if '.' in code: code=code.replace('.','') num.append('.'+fontcodes[code]) else: num.append(fontcodes[code]) infos=['排行:'+str(index+1), '片名',name, '上映首日',movieDayOne[name], '票房',''.join(num)+'萬', '票房佔比',movieRate[name], '場均人數',movieViewerAvg[name]+'人', '排片場次',movieshowCount[name]] print(infos)
最新評論
|