python爬蟲:某網站價格數字加密破解

文章目錄

  • 前言
  • 一、案例
  • 二、破解流程
    • 1.原理
    • 2.找到woff文件
    • 3.分析woff文件
    • 4.代碼實現
        • 1.轉化woff文件
        • 2.繪圖并ocr識別
        • 3.映射數據
  • 三、總結


前言

有時我們在進行網頁抓取采集數據時,有些重要的數據比如說價格,數量等信息會進行加密,通過復制或者簡單的采集是無法采集到編碼后的文字內容的,現在貌似有不少網站都有采用這種反爬機制,作為爬蟲工程師,還是要了解甚至掌握這個技巧的。

一、案例

在這里插入圖片描述

在某網站商品價格展示,打開F12 ,數字和符號是做了替換,顯示為???????,所以如果我們想獲取所看到的價格就要花些功夫。

二、破解流程

1.原理

其實這就是CSS反爬,CSS字體反爬是一種通過使用自定義字體和字符映射來保護頁面內容的技術。在這類技術中,網頁上的文本并非直接展示為標準字符,而是通過特殊設計的字體顯示。這樣,即使爬蟲抓取到頁面源代碼,獲得的卻是字體文件的引用,而不是實際的字符內容。
通常,這些字體文件是通過 JavaScript 動態加載的,而且在字體文件中,每個字符與其對應的可視形態之間存在一個映射關系。只有瀏覽器能夠正確渲染這些映射,爬蟲則無法直接讀取到有效的文本內容,需要我們間接獲取解析處理。

2.找到woff文件

第一種方法,通過標簽class的屬性值,例如上圖中class值:fontf04dfc98 全局搜索:
在這里插入圖片描述

第二種方法:也是全局搜索font-face,也是同樣的效果

3.分析woff文件

把上圖帶有woff字樣的鏈接下載到本地,使用FontEditor打開woff文件,鏈接地址:https://font.qqe2.com/index.html?src=www.jspoo.com
在這里插入圖片描述
發現這上面的字符串跟網頁的???????不一樣,那我們嘗試點擊預覽按鈕,切換eot字體如下圖:
在這里插入圖片描述
會彈出另一個窗口,兩個窗口內容進行比較
在這里插入圖片描述
我們是不是已經發現了網頁的不規范數字1對應?,這是不是就對應上了,接下來就是代碼實現這個流程的問題

4.代碼實現

1.轉化woff文件
from fontTools.ttLib import TTFont
font = TTFont('tansoole.woff')
font.saveXML('tansoole.xml')

運行代碼并打開部分標簽,如圖:
在這里插入圖片描述

# 可以轉化獲取name值def extract_font_data_from_woff(woff_file_path):font = TTFont(woff_file_path)cmap = font.getBestCmap()code_to_name = {}for code, name in cmap.items():code_to_name[code] = namereturn code_to_namewoff_file_path = 'tansoole.woff'unicode_mapping = extract_font_data_from_woff(woff_file_path)print(unicode_mapping)#打印信息# {0: '.null', 29: '.null', 287: 'gbreve', 292: 'Hcircumflex', 298: 'Imacron', 335: 'obreve', 341: 'racute', 362: 'Umacron', 381: 'Zcaron', 453: 'uni01C5', 459: 'uni01CB', 540: 'uni021C', 548: 'uni0224', 550: 'uni0226'}# 轉化對應eot對應關系
Mapping_tables = {}
for code, mapping in unicode_mapping.items():character_key = chr(code)character_value = mappingMapping_tables[character_key] = character_value
print(Mapping_tables)
# 打印信息
# {'\x00': '.null', '\x1d': '.null', '?': 'gbreve', '?': 'Hcircumflex', 'ī': 'Imacron', '?': 'obreve', '?': 'racute', 'ū': 'Umacron', '?': 'Zcaron', '?': 'uni01C5', '?': 'uni01CB', '?': 'uni021C', '?': 'uni0224', '?': 'uni0226'}
2.繪圖并ocr識別
import os
import timeimport ddddocrfrom fontTools.ttLib.ttFont import TTFont
from fontTools.pens.svgPathPen import SVGPathPen
import matplotlib.pyplot as plt
import matplotlib.patches as patches
from matplotlib.path import Path
import matplotlib._color_data as mcddef ttf_to_char(font_file, glyph_set_name=None, temp_png_path="./"):# %matplotlib inline# 加載字體font = TTFont(font_file)# 7.1 生成PNG圖片# 7.1.1 第一步提取繪制命令語句# 獲取包含字形名稱和字形對象的--字形集對象glyphsetglyphset = font.getGlyphSet()# print(glyphset.keys())# 獲取pen的基類pen = SVGPathPen(glyphset)# 查找"馬"的字形對象glyph = glyphset[glyph_set_name]# 繪制"馬"的字形對象glyph.draw(pen)# 提取"馬"的繪制語句commands = pen._commands# print(commands)total_commands = []command = []for i in commands:# 每一個命令語句if i == 'Z':# 以閉合路徑指令Z區分不同輪廓線command.append(i)total_commands.append(command)command = []else:command.append(i)# 從'head'表中提取所有字形的邊界框xMin = font['head'].xMinyMin = font['head'].yMinxMax = font['head'].xMaxyMax = font['head'].yMax# print("所有字形的邊界框: xMin = {}, xMax = {}, yMin = {}, yMax = {}".format(xMin, xMax, yMin, yMax))# 所有字形的邊界框: xMin = -12, xMax = 264, yMin = -47, yMax = 220preX = 0.0preY = 0.0# 筆的起始位置startX = 0.0startY = 0.0# 所有輪廓點total_verts = []# 所有指令total_codes = []# 轉換命令for i in total_commands:# 每一條輪廓線verts = []codes = []for command in i:# 每一條輪廓線中的每一個命令code = command[0]  # 第一個字符是指令vert = command[1:].split(' ')  # 其余字符是坐標點,以空格分隔# M = 路徑起始 - 參數 - 起始點坐標 (x y)+if code == 'M':codes.append(Path.MOVETO)  # 轉換指令verts.append((float(vert[0]), float(vert[1])))  # 提取x和y坐標# 保存筆的起始位置startX = float(vert[0])startY = float(vert[1])# 保存筆的當前位置(由于是起筆,所以當前位置就是起始位置)preX = float(vert[0])preY = float(vert[1])# Q = 繪制二次貝塞爾曲線 - 參數 - 曲線控制點和終點坐標(x1 y1 x y)+elif code == 'Q':codes.append(Path.CURVE3)  # 轉換指令verts.append((float(vert[0]), float(vert[1])))  # 提取曲線控制點坐標codes.append(Path.CURVE3)  # 轉換指令verts.append((float(vert[2]), float(vert[3])))  # 提取曲線終點坐標# 保存筆的當前位置--曲線終點坐標x和ypreX = float(vert[2])preY = float(vert[3])# C = 繪制三次貝塞爾曲線 - 參數 - 曲線控制點1,控制點2和終點坐標(x1 y1 x2 y2 x y)+elif code == 'C':codes.append(Path.CURVE4)  # 轉換指令verts.append((float(vert[0]), float(vert[1])))  # 提取曲線控制點1坐標codes.append(Path.CURVE4)  # 轉換指令verts.append((float(vert[2]), float(vert[3])))  # 提取曲線控制點2坐標codes.append(Path.CURVE4)  # 轉換指令verts.append((float(vert[4]), float(vert[5])))  # 提取曲線終點坐標# 保存筆的當前位置--曲線終點坐標x和ypreX = float(vert[4])preY = float(vert[5])# L = 繪制直線 - 參數 - 直線終點(x, y)+elif code == 'L':codes.append(Path.LINETO)  # 轉換指令verts.append((float(vert[0]), float(vert[1])))  # 提取直線終點坐標# 保存筆的當前位置--直線終點坐標x和ypreX = float(vert[0])preY = float(vert[1])# V = 繪制垂直線 - 參數 - 直線y坐標 (y)+elif code == 'V':# 由于是垂直線,x坐標不變,提取y坐標x = preXy = float(vert[0])codes.append(Path.LINETO)  # 轉換指令verts.append((x, y))  # 提取直線終點坐標# 保存筆的當前位置--直線終點坐標x和ypreX = xpreY = y# H = 繪制水平線 - 參數 - 直線x坐標 (x)+elif code == 'H':# 由于是水平線,y坐標不變,提取x坐標x = float(vert[0])y = preYcodes.append(Path.LINETO)  # 轉換指令verts.append((x, y))  # 提取直線終點坐標# 保存筆的當前位置--直線終點坐標x和ypreX = xpreY = y# Z = 路徑結束,無參數elif code == 'Z':codes.append(Path.CLOSEPOLY)  # 轉換指令verts.append((startX, startY))  # 終點坐標就是路徑起點坐標# 保存筆的當前位置--起點坐標x和ypreX = startXpreY = startY# 有一些語句指令為空,當作直線處理else:codes.append(Path.LINETO)  # 轉換指令verts.append((float(vert[0]), float(vert[1])))  # 提取直線終點坐標# 保存筆的當前位置--直線終點坐標x和ypreX = float(vert[0])preY = float(vert[1])# 整合所有指令和坐標total_verts.append(verts)total_codes.append(codes)color_list = list(mcd.CSS4_COLORS)# 獲取所有的輪廓坐標點total_x = []total_y = []for contour in total_verts:# 每一條輪廓曲線x = []y = []for i in contour:# 輪廓線上每一個點的坐標(x,y)x.append(i[0])y.append(i[1])total_x.append(x)total_y.append(y)if total_x == [[186.0, 186.0, 391.0, 391.0, 186.0]]:return '.'if total_x == [[0.0, 425.0, 569.0, 145.0, 0.0]]:return '/'# 創建畫布窗口fig, ax = plt.subplots()# 按照'head'表中所有字形的邊界框設定x和y軸上下限ax.set_xlim(xMin, xMax)ax.set_ylim(yMin, yMax)# 設置畫布1:1顯示ax.set_aspect(1)# 添加網格線# ax.grid(alpha=0.8,linestyle='--')# 畫圖# print(f"{glyph_set_name}======繪制圖片=======")for i in range(len(total_codes)):# (1)繪制輪廓線# 定義路徑path = Path(total_verts[i], total_codes[i])# 創建形狀,無填充,邊緣線顏色為color_list中的顏色,邊緣線寬度為2patch = patches.PathPatch(path, facecolor='none', edgecolor=color_list[i + 10], lw=2)# 將形狀添到圖中ax.add_patch(patch)# (2)繪制輪廓點--黑色,點大小為10# ax.scatter(total_x[i], total_y[i], color='black',s=10)# 保存圖片temp_path = f"{temp_png_path}/temp{int(time.time()*100000)}.png"plt.savefig(temp_path)plt.close()# print(f"{glyph_set_name}======保存圖片=======")with open(temp_path, "rb") as f:content = f.read()# print(f"{glyph_set_name}=====DdddOcr開始識別文字=======")dddd = ddddocr.DdddOcr(show_ad=False)text = dddd.classification(content)if os.path.exists(temp_path):os.remove(temp_path)return textif __name__ == '__main__':# glyph_set_name 就是上圖中的name值  這樣映射關系都對應上了res = ttf_to_char('tansoole.woff',glyph_set_name='gbreve')print(res)
3.映射數據

最后將上圖代碼流程已經結果字典映射對應就有了我們所看到的值,如圖所示:
在這里插入圖片描述


三、總結

在字體反爬的路還有很長的路要走,本文也是筆者一些經驗和不成熟的見解,也歡迎跟各位大佬一起交流學習!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/87361.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/87361.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/87361.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

DigitalOcean 攜手 AMD 推出 AMD Instinct? MI300X GPU Droplet,加速 AI 創新

近日,DigitalOcean(NYS:DOCN)作為全球最簡單易用的可擴展云平臺,宣布與 AMD 建立合作,為 DigitalOcean 客戶提供 AMD Instinct? GPU,以 AMD Instinct? MI300X GPU Droplet 的形式支持其 AI 工作負載。此舉…

小白暢通Linux之旅-----DNS項目實戰配置

目錄 一、項目要求 1、正反向解析配置 2、主從配置 二、腳本編寫配置 1、主服務器腳本編寫 2、從服務器腳本編寫 三、項目檢測 1、正反向解析檢測 (1)主服務器腳本啟動 (2)測試主機配置 (3)正反…

Codigger:探索數字工作新架構

在軟件開發與數字工作領域,技術迭代的腳步從未停歇,開發者和系統管理員都在尋找更高效的工具和平臺。Codigger 作為一項創新技術成果,憑借其獨特的定位和架構,在行業內逐漸嶄露頭角。 Codigger “分布式操作系統”,它…

微信中 qrcode 生成二維碼長按無效果的解決方案

引言 我們先來看這樣一段代碼 <divid"qrcode"ref"qrcode"class"bind-code-img"style"height: 180px;width: 180px;margin-top: 22px;display: none; "></div> new QRCode("qrcode", {width: 210,height: 210,t…

《網絡安全與防護》作業復習

填空題 1. 網絡數據庫與數據安全專項作業 填空題解析&#xff1a; 數據庫安全的“三大核心目標”是 完整性&#xff1b;保密性&#xff1b;可用性 解釋&#xff1a;數據庫安全的三個核心目標是確保數據的完整性、保密性以及可用性&#xff0c;即保護數據不被篡改、未經授權訪…

【windows常見文件后綴】

文件后綴解釋css層疊樣式表&#xff08;Cascading Style Sheets&#xff09;&#xff1a;用于描述HTML或XML&#xff08;包括如SVG、XHTML等XML方言&#xff09;文檔的呈現樣式&#xff0c;控制網頁的布局、顏色、字體等視覺效果。jsJavaScript&#xff1a;一種輕量級的解釋型或…

labelme啟動報錯動態鏈接庫DLL初始化例程失敗

安裝 pip install labelme啟動 labelmewin11python3.12&#xff0c;pycharm venv 安裝&#xff1a; pip install labelme&#xff0c;啟動labelme報錯&#xff1a; 降級numpy&#xff0c;降級onnxruntime pip install “numpy<2.0” pip install onnxruntime1.18.0 再次cm…

Mybatis(javaweb第九天)

Mybatis基礎操作 占位符&#xff1a;#{變量名} 注意事項&#xff1a;如果Mapper接口方法只有一個普通類型參數&#xff0c;屬性名可以隨便寫 > Preparing: delete from emp where id? > Parameters: 1(Integer) 預編譯SQL 不會將值直接放在SQL語句中&#xff0c;而是…

C#開發MES管理系統源碼工業生產線數據采集WPF上位機產線執行系統源碼

該源碼是實際生產線運行的實際項目&#xff0c;全套源碼。適合開發者學習參考&#xff0c;有需要源碼可以聯系博主

`ngx_otel_module` NGINX OpenTelemetry 分布式追蹤實戰

1. 模塊簡介 ngx_otel_module 為 NGINX&#xff08;開源版 1.25.3&#xff0c;商業版 1.23.4&#xff09;提供了 OpenTelemetry&#xff08;OTel&#xff09;分布式追蹤支持&#xff0c;能夠&#xff1a; 自動采集 HTTP 請求的生命周期 Span上下文傳播&#xff1a;兼容 W3C t…

Vue+TypeScript 枚舉(Enum)的使用規范

在 TypeScript 中&#xff0c;枚舉&#xff08;Enum&#xff09;的命名應遵循以下規范&#xff0c;這些規范結合了 TypeScript 官方建議和行業最佳實踐&#xff1a; 枚舉命名規范&#xff08;TypeScript/Vue 項目&#xff09; 基本命名規則&#xff1a; 使用 PascalCase&#…

一個完整的LSTM風光發電預測與并網優化方案,包含數據處理、模型構建、訓練優化、預測應用及系統集成實現細節

以下是一個完整的LSTM風光發電預測與并網優化方案,包含數據處理、模型構建、訓練優化、預測應用及系統集成實現細節: 風光發電功率預測與并網優化系統 基于LSTM的時間序列預測與儲能協同控制 第一部分:系統架構設計(1200字) 1.1 整體技術路線 #mermaid-svg-U5pxzefmzZ4s…

如何在 MX Linux 上安裝 Mint 的 Cinnamon 桌面 UI

如何在 MX Linux 上安裝 Mint 的 Cinnamon 桌面 UI 你是否想在 MX Linux 上安裝流行的 Linux Mint Cinnamon 圖形用戶界面?那么這里有一個教程…… Cinnamon 是一個類似 Windows 7 的界面,它默認安裝在 Linux Mint 操作系統中。它使 Mint 非常易于理解和使用,這也是 Mint …

OpenStack 入門

目錄 簡介 一、云計算與 OpenStack 基礎概念 1.1 云計算概述 1.2 OpenStack 簡介 二、OpenStack 單機環境部署 2.1 環境準備 2.2 部署前準備工作 2.3 在線部署 OpenStack&#xff08;Train 版本&#xff09; 三、通過 Dashboard 部署 OpenStack 的功能 3.1 登錄 Dash…

【Git】關于項目開發分支的使用規范

背景 在項目開發過程中&#xff0c;往往一個優秀的產品都會出現不斷的版本迭代&#xff0c;我時常在項目發布后對于如何結合后續更新的業務場景在分支上的應用沒有一個很好的辦法&#xff0c;一直也比較苦惱。目前項目的迭代場景如下&#xff0c;一個A項目&#xff0c;經過需求…

msquic的windows版本編譯

首先確保安裝cmake和powershell&#xff08;需要6以上&#xff0c;本人升級到了7.5&#xff09;&#xff0c;vs&#xff08;本人用的vs2022&#xff09; powershell&#xff0c;默認是5&#xff0c;會編譯不成功&#xff0c;所以附帶一個升級的流程 $PSVersionTable.PSVersion …

批量文件重命名工具 OncePower ,永久免費!

軟件介紹 適用于Windows OncePower是一款Windows批量重命名工具&#xff0c;支持基本及高級匹配重命名&#xff0c;無需復雜正則。特色包括匹配修改、長度截取、日期命名、前綴后綴修改及TXT文件導入。支持保留特定內容、批量移動文件和刪除空文件夾。可保存設置&#xff0c;…

Python入門Day6.1:異常處理

一、什么是異常&#xff08;Exception&#xff09;&#xff1f; 異常是指程序運行過程中出現的錯誤情況。比如&#xff1a; 打開一個不存在的文件0作為除數列表索引越界類型轉換失敗 二、基本結構&#xff1a;try...except try:# 可能出錯的代碼 except 錯誤類型:# 出錯時執…

C++中的標準模板(STL)

C中的核心標準模板包含&#xff1a;容器、迭代器、算法、函數對象、適配器。 1.容器 容器提供了各種數據結構&#xff0c;包括向量(vector)、鏈表(list)、隊列(queue)、棧(stack)、集合(set)、映射(map)等&#xff0c;可以根據實際需求選擇合適的容器。 容器分為三大類&…

excel 待辦日歷軟件(需要宏)特別推薦

Excel待辦日歷軟件是一款基于Excel表格的日程管理工具&#xff0c;能夠幫助用戶更高效地管理待辦事項和日程安排。用戶可以在軟件中創建不同的任務列表&#xff0c;以便更好地進行管理和跟蹤。軟件還提供了日歷視圖&#xff0c;用戶可以直觀地查看和安排每日的任務&#xff0c;…