【Python3爬蟲】貓眼電影爬蟲(破解字符集反爬)


一、頁面分析

首先打開貓眼電影,然后點擊一個正在熱播的電影(比如:毒液)。打開開發者工具,點擊左上角的箭頭,然后用鼠標點擊網頁上的票價,可以看到源碼中顯示的不是數字,而是某些根本看不懂的字符,這是因為使用了font-face定義字符集,並通過unicode去映射展示,所以我們在網頁上看到的是數字,但是在源碼中看到的卻是別的字符。

碰到這些根本看不懂的字符怎么辦呢?不慌,右鍵選擇查看網頁源代碼,然后找到相應的位置(如下圖)。那么是不是“”映射出來就是28呢?

通過查看源碼,可以找到如下內容, 而當我們訪問這里面的鏈接的時候,就可以下載相應的字體文件,關於font-face可以點擊這里查看了解:

當我下載好字體文件后,滿心歡喜的雙擊想要點開的時候,卻發現無法打開(T_T)。查閱資料之后知道了一個叫做FontCreator的軟件,用這個軟件可以打開我們下載的字體文件,沒有安裝這個軟件的可以進入官網https://www.high-logic.com/下載安裝,如果下載得很慢的可以用百度雲下載(鏈接:https://pan.baidu.com/s/1ImxwPhKdzZo2g4bIjiGCZw ,提取碼:m0yf )。下載好之后打開軟件,看到如下界面,選擇Use Evaluation Version,這個軟件我們可以免費使用三十天。

 

打開軟件后,再打開我們下載的字體文件,可以看到數字2和8分別對應的是uniE83B和uniE375,和前面看到的編碼是一致的。

 

那么我們下載好字符集之后,只要將其中的字符編碼和數字對應的信息提取出來,再把網頁源碼中的字符編碼替換掉,就能得到我們想要的數據了。這里要用到一個三方庫fontTools,利用fontTools可以獲取每一個字符對象,這個對象你可以簡單的理解為保存着這個字符的形狀信息,而且編碼可以作為這個對象的id,具有一一對應的關系。不過這里還有一個問題,就是網頁每次使用的字符集是隨機變化的,我們也就無法使用一個固定的字符集去做到反爬。

解決思路如下:先保存一個字體文件(比如base.woff),然后解析其數字和編碼的對應關系,然后爬取的時候把新的字體文件下載下來(比如online.woff),網頁中的一個數字的編碼(比如ABCD),我們先通過編碼ABCD找到這個字符在online.woff中的對象,並且把它和base.woff中的對象逐個對比,直到找到相同的對象,然后獲取這個對象在base.woff中的編碼,再通過編碼確認是哪個數字。

 

二、主要代碼

解析下載的字體文件,由於字體文件中有多余的字符,需要舍棄掉。

 1 # 解析字體庫
 2 def parse_ttf(font_name):
 3     """
 4     :param font_name: 字體文件名
 5     :return: 字符-數字字典
 6     """
 7     base_nums = ['3', '0', '1', '6', '4', '2', '5', '8', '9', '7']
 8     base_fonts = ['uniEB84', 'uniF8CA', 'uniEB66', 'uniE9DB', 'uniE03C',
 9                   'uniF778', 'uniE590', 'uniED12', 'uniEA5E', 'uniE172']
10     font1 = TTFont('base.woff')  # 本地保存的字體文件
11     font2 = TTFont(font_name)  # 網上下載的字體文件
12 
13     uni_list = font2.getGlyphNames()[1:-1]  # 去掉頭尾的多余字符
14     temp = {}
15     # 解析字體庫
16     for i in range(10):
17         uni2 = font2['glyf'][uni_list[i]]
18         for j in range(10):
19             uni1 = font1['glyf'][base_fonts[j]]
20             if uni2 == uni1:
21                 temp["&#x" + uni_list[i][3:].lower() + ";"] = base_nums[j]
22     return temp

解析網頁源碼,把其中的編碼替換成數字,這里選擇把網頁源碼保存下來,這樣的話編碼就不會改變,也就能正確的解析。

 1 # 解析網頁得到數字信息
 2 def get_nums(font_dict):
 3     """
 4     :param font_dict: 字符-數字字典
 5     :return: 由評分、評分人數、票房和票價組成的列表
 6     """
 7     num_list = []
 8     with open('html', 'r', encoding='utf-8') as f:
 9         for line in f.readlines():
10             lst = re.findall('(&#x.*?)<', line)
11             if lst:
12                 num = lst[0]
13                 for i in font_dict.keys():
14                     if i in num:
15                         num = num.replace(i, font_dict[i])
16                 num_list.append(num)
17     return num_list

 

三、運行結果

 

完整代碼已上傳到GitHub


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM