今天的目標網站是某彩票網站博X網。其主要的反爬技術爲字體反爬,話不多說,我們直接開始!
我們想要獲取的是具體的開獎號碼,此號碼是通過藍色的小球表示的,如何獲取呢?
觀察NetWork後,我們很容易發現這些號碼數據等信息都以json的形式放在下圖紅色圈出的html頁面中。
而這些號碼數據是以類似於󿓥這種形式表示的(上圖中藍色框部分)。
因此,我們的爬取路線可以分兩步走,先設法獲取該json數據,繼而通過某種方式將數據中的編碼轉換爲正常的數字。
JSON獲取
觀察該頁面的Headers數據,可知爲POST請求,其表單數據格式如下圖所示,
反覆刷新頁面發現code和limit是固定的參數,而path是不斷變化的,因而我們需要找到path參數才能夠構造POST請求訪問頁面並獲取數據。
我們複製當前的path參數到搜索框搜索,發現有兩個頁面包含該path參數。
txffc.html這個頁面正是我們爬取的目標頁面,我們只需要從該頁面的網頁源代碼中通過正則表達式獲取該path參數即可,也就是代碼中的woff_id。
從另外一個頁面,我們可以下載對應path的woff字體文件,並藉此解碼出這些數據,後面會詳細講。
得到path參數之後,我們可以輕鬆的構建POST請求,並獲取到相應的json數據,這裏建議選擇Headers參數的時候,除了User-Agent,記得將網頁請求攜帶的所有參數帶上,以防無法正常獲取數據。
字體反爬
上面講到,根據path我們已經可以獲取相應的woff文件,用FontCreator打開看看。
我們可以看到0-9一共十個數字,json數據中的󿓥正是通過這樣的字體文件轉換的。
這裏出現了幾個難點。
字體文件實時變化,人工的方法只能每爬取一次,根據woff文件做一次轉換,來得到想要的數據;
不同時刻字體文件有些出入,比如上圖包含很多問號也就是無效的字符,而有些則不包含,比如下圖;
這些字體對象的name和code不一致(與貓眼等網站不同),需要構建新的映射關係;
數字9的字體座標位置並不完全相同。
這些問題自然是需要一個一個來解決。首先我們需要一個參照系,人工標識出字體的對應關係(base_dict),從而當新字體文件引入的時候,我們可以根據這個參照獲得新的映射關係。
base_dict={'glyph00009': 7, 'glyph00013': 2, 'glyph00018': 1, 'glyph00023': 6, 'glyph00028': 9, 'glyph00030': 8,'glyph00034': 4, 'glyph00039': 5, 'glyph00044': 3, 'glyph00048': 0}
通過get_new_name_list函數來篩選出有效的字體,上述的問號字體是不存在coordinates屬性的。
由於該網站不同的字體文件數字9的座標位置有些許不同,這裏採用對比字體前十個座標來做判斷,如果完全相同,則認爲對應的字體是相同的數字。
我們由此可以得到新的字典new_dict——它的鍵爲新字體文件的字體對象的name,值爲字體對應的數字。
{'glyph00002': 6, 'glyph00003': 1, 'glyph00004': 0, 'glyph00005': 4, 'glyph00006': 7, 'glyph00007': 5, 'glyph00008': 8, 'glyph00009': 9, 'glyph00010': 3, 'glyph00011': 2}
接着爲了對應編碼與數字,我們需要重新建立新的字體映射表。通過getBestCmap函數,獲取對應字體的name與code之間的關係,由此我們可以得到映射表——鍵爲編碼,值爲數字,需要注意的是由於getBestCmap()會將內容轉化爲10進制,因此在後面存入字典的時候需要轉化爲16進制。
通過該映射表,我們可以輕鬆將獲取地json數據相關部分轉換爲可讀的數字。至此,我們就成功地解決了該網站的字體反爬。關於其他幾個經典的字體反爬網站,可以參考專輯裏面的文章~
——END——
推薦閱讀