Python反反爬系列(一)----K近鄰演算法與CSS動態字型加密
1.字型反爬
字型反爬也就是自定義字型加密對映,透過呼叫自定義的字型檔案來渲染網頁中的文字,而網頁中的文字不再是文字,而是相應的字型編碼,透過複製或者簡單的採集是無法採集到編碼後的文字內容的。
2.檢視字型軟體font creator 可下載,也可不下載,藉助網頁版工具
3.CSS處理前後的字型
我們看到的網頁上的資料是正常的
但是當我們開啟開發者工具檢查字型時 ,金額和票房資料卻變成了類似亂碼的字元
我們再檢查網頁原始碼,發現資料和上面的都不一樣,而且每次請求金額還被加密成不同的密文
多次請求,發現返回的字型檔案重複機率太低(仔細觀察是有的,就是少)
4.解決思路
瞭解CSS 的應該會知道(我不知道),CSS 中有一個 @font-face,它允許網頁開發者為其網頁指定線上字型。原本是用來消除對使用者電腦字型的依賴,現在有了新作用——字型反爬。具體的請檢視 https://developer.mozilla.org/zh-CN/docs/Web/CSS/@font-face 再觀察原始碼中的資料,像是編碼過後的資料。
仔細觀察發現是一些特定span中的資料經過處理,如下圖
所以我們就查詢該class名,找到了其字型樣式
其中的woff就是字型檔案,還有其他的,比如ttf字型,woff2,svg等,這裡僅有woff ,可在font欄檢視
將該字型下載過來,在json字型編輯器中開啟,https://font.qqe2.com/,可看到字型,多次重新整理的話同樣的數字還不一樣
我們再次拿處理前後的部分數字拿來進行對比:
最初數字 2 4 0 1 . 3
加密後 .
字型中 $E290 $ED17 $F1A7 $EFBD $EFBD
uniE290 uniED17 uniF1A7 uniEFBD uniEFBD
發現規律了吧,但是我們知道每次數字位置都是動態...
5.用TTfont把woff檔案轉化成xml檔案
先將字型轉化成xml檔案。
import requests
from fontTools.ttLib import TTFont
def woff_xml():
url = "
woff_dir = r"./colorstone/"
file_name = url.split("/")[-1]
xml_name = file_name.replace(file_name.split(".")[-1], "xml")
save_woff = file_name
save_xml = xml_name
resp = requests.get(url=url)
with open(woff_dir+save_woff, "wb") as f:
f.write(resp.content)
f.close()
font = TTFont(woff_dir+save_woff)
font.saveXML(woff_dir+save_xml)
轉換成的資料如圖:
仔細檢視後,確定和我們字型相關的標籤: 和 ,其中標籤中的資料在上圖,我們對進行檢視:
其中有x,y,Xmin,Ymin,Xmax,Ymax等值,很明顯是一些座標點的資訊,其實他就是確定字型形狀的座標,不信我們可以畫一下: 鄭州人流醫院
import matplotlib.pyplot as plt
import re
str = """"
相應內容複製上來
"""
x = [int(i) for i in re.findall(r'
獲取10套基準字型,最初是存到XML中的,後面發現沒必要
:return: None
'''
for i in range(0,10):#獲取10套字型作為基準字型
time.sleep(1)
res = requests.get(url=self.start_url,headers=self.headers,proxies=self.proxies)
res.encoding = "utf-8"
part_font_url = re.findall(r"url\('(.{,100}?\.woff)",res.text,re.S)
#請求一次獲得部分url
if part_font_url:
font_url = "https:" + part_font_url[0]
file_name = str(i+1)+".woff" #字型檔案1.woff
save_woff = file_name
resp = requests.get(url=font_url,proxies=self.proxies)
try:
with open(r"./colorstone/" + save_woff, "wb") as f:#將woff檔案儲存
f.write(resp.content)
f.close()
# font = TTFont(r"./colorstone/" + save_woff)
# font.saveXML(r"./colorstone/base" + str(i+1)+ ".xml") #儲存為base1.xml這樣的檔名
print("第{}套基準字型儲存完畢!".format((i+1)))
except Exception as e:
print(e)
else:
print("第{}次請求失敗,請檢查網站是否禁止訪問等".format((i+1)))
6.2.提取樣本字型中的數字 + 座標:
def base_font(self):
'''
獲取10套基準字型中數字對應的x,y值
:return: None
'''
# 檢視10套基準字型, 獲取數字順序
# base_num1 = [3,8,9,2,0,1,7,5,4,6]
# base_num2 = [3,6,5,2,4,8,9,1,7,0]
# base_num3 = [6,0,4,8,1,9,5,2,3,7]
# base_num4 = [1,8,2,5,7,9,4,6,3,0]
# base_num5 = [0,9,8,6,1,4,7,3,2,5]
# base_num6 = [9,7,5,8,3,4,6,1,2,0]
# base_num7 = [6,5,9,4,0,2,8,3,1,7]
# base_num8 = [6,5,1,0,4,7,8,2,9,3]
# base_num9 = [0,6,9,5,3,8,4,1,2,7]
# base_num10 = [0,6,2,8,5,9,5,3,1,7]
base_num = [[3,8,9,2,0,1,7,5,4,6],[3,6,5,2,4,8,9,1,7,0],[6,0,4,8,1,9,5,2,3,7],[1,8,2,5,7,9,4,6,3,0],
[0,9,8,6,1,4,7,3,2,5],[9,7,5,8,3,4,6,1,2,0],[6,5,9,4,0,2,8,3,1,7],[6,5,1,0,4,7,8,2,9,3],
[0,6,9,5,3,8,4,1,2,7],[0,6,2,8,5,9,5,3,1,7]]
num_coordinate = []
for i in range(0,10):
woff_path = "./colorstone/"+str(i+1)+".woff"
font = TTFont(woff_path)
obj1 = font.getGlyphOrder()[2:] #過濾到前兩個不需要的
for j, g in enumerate(obj1):
coors = font['glyf'][g].coordinates
coors = [_ for c in coors for _ in c]
coors.insert(0, base_num[i][j])
num_coordinate.append(coors)
return num_coordinate
6.3. 在函式knn(self)中:
6.3.1 獲取特徵值,目標值
num_coordinate = self.base_font()
data = pd.DataFrame(num_coordinate)
data = data.fillna(value=0)
x = data.drop([0],axis=1)
y = data[0]
6.3.2 進行資料的分割:訓練集和測試集
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.25)
6.3.3 呼叫KNN演算法(這裡n的引數由網格驗證得出,最優引數為1):
knn = KNeighborsClassifier(n_neighbors=1)
knn.fit(x_train, y_train)
6.4.建立對映,將數字和對應的編碼建成字典形式:
def get_map(self):
font = TTFont("./colorstone/target.woff")
glyf_order = font.getGlyphOrder()[2:]
info = []
for g in glyf_order:
coors = font['glyf'][g].coordinates
coors = [_ for c in coors for _ in c]
info.append(coors)
print(info)
knn,length = self.knn()
df = pd.DataFrame(info)
data = pd.concat([df, pd.DataFrame(np.zeros(
(df.shape[0], length - df.shape[1])), columns=range(df.shape[1], length))])
data = data.fillna(value=0)
y_predict = knn.predict(data)
num_uni_dict = {}
for i, uni in enumerate(glyf_order):
num_uni_dict[uni.lower().replace('uni', '&#x') + ';'] = str(y_predict[i])
return num_uni_dict
6.5.採集資料並替換,獲取正確資料:
根據網頁結構,提取資料:
def get_info(self):
res = requests.get(url=self.start_url, headers=self.headers)
res.encoding = "utf-8"
part_font_url = re.findall(r"url\('(.{,100}?\.woff)", res.text, re.S)
# 請求一次獲得部分url
if part_font_url:
font_url = "https:" + part_font_url[0]
resp = requests.get(url=font_url,proxies=self.proxies)
with open(r"./colorstone/target.woff", "wb") as f: # 儲存需要分析的字型檔案
f.write(resp.content)
f.close()
html = res.text
map_dict = self.get_map()
for uni in map_dict.keys():
html = html.replace(uni, map_dict[uni])
parse_html = etree.HTML(html)
for i in range(0,11):
name = parse_html.xpath('//dd[{}]//p[@class="name"]/a/@title'.format(i))
star = parse_html.xpath('//dd[{}]//p[@class="star"]/text()'.format(i))
releasetime = parse_html.xpath('//dd[{}]//p[@class="releasetime"]/text()'.format(i))
realtime_amount= parse_html.xpath('//dd[{}]//p[@class="realtime"]//text()'.format(i))
total_amount = parse_html.xpath('//dd[{}]//p[@class="total-boxoffice"]//text()'.format(i))
print("".join(name)," ","".join(star)," ","".join(releasetime),"".join(realtime_amount).replace(" ","").replace("\n",""),"".join(total_amount).replace(" ",""))
列印結果
對比原網頁
資料完全是一樣的,此次動態字型反爬到此就結束了。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69945560/viewspace-2671207/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Python:K-近鄰演算法Python演算法
- K - 近鄰演算法演算法
- K近鄰演算法演算法
- 2.1 k鄰近演算法之一演算法
- 機器學習——K近鄰演算法機器學習演算法
- k-近鄰演算法演算法
- K-鄰近均值演算法演算法
- 機器學習-K近鄰演算法-KNN機器學習演算法KNN
- 用Python實現K-近鄰演算法Python演算法
- K近鄰模型模型
- k近鄰演算法python實現 -- 《機器學習實戰》演算法Python機器學習
- 機器學習-11-k近鄰演算法機器學習演算法
- 2.1 k鄰近演算法之二演算法
- 分類演算法-k 鄰近演算法演算法
- 機器學習演算法之K近鄰演算法機器學習演算法
- 反爬與反反爬
- 機器學習實戰----k值近鄰演算法(Python語言)機器學習演算法Python
- 機器學習演算法——kNN(k-近鄰演算法)機器學習演算法KNN
- 機器學習——KNN(K近鄰)機器學習KNN
- K-近鄰演算法介紹與程式碼實現演算法
- 機器學習_K近鄰Python程式碼詳解機器學習Python
- 機器學習實戰筆記-k近鄰演算法機器學習筆記演算法
- k近鄰演算法的實現:kd樹演算法
- 機器學習筆記1(K-近鄰演算法)機器學習筆記演算法
- K近鄰演算法:機器學習萌新必學演算法演算法機器學習
- 機器學習演算法(三):K近鄰(k-nearest neighbors)初探機器學習演算法REST
- 第一篇:K-近鄰分類演算法原理分析與程式碼實現演算法
- K近鄰法(KNN)原理小結KNN
- C#爬蟲與反爬蟲--字型加密篇C#爬蟲加密
- 機器學習——KNN近鄰演算法機器學習KNN演算法
- 用定租問題學透機器學習的K近鄰演算法機器學習演算法
- 統計學習筆記(3)——k近鄰法與kd樹筆記
- 記一次css字型反爬CSS
- 機器學習——最鄰近規則分類(K Nearest Neighbor)KNN演算法機器學習RESTKNN演算法
- 機器學習實戰2.1. 超詳細的k-近鄰演算法KNN(附Python程式碼)機器學習演算法KNNPython
- k-鄰近演算法實現約會網站的配對效果演算法網站
- 【機器學習】機器學習建立演算法第2篇:K-近鄰演算法【附程式碼文件】機器學習演算法
- 2.2:示例,使用k鄰近演算法改進約會網站的配對效果 之一演算法網站