反爬篇 | 手把手教你處理 JS 逆向之 SVG 映射

大家好,我是安果!
前面三篇文章分別從圖片偽裝、字體反爬、CSS 偏移這 3 個方面,講解了應對這類反爬網(wǎng)站時的解決方案
本篇文章聊聊另外一種常見的反爬方案,即:「 SVG 映射 」
SVG 全稱為?Scalable Vector Graphics,是一種基于 XML 并可以縮放的矢量圖片文件格式
而 SVG 反爬是利用 CSS 樣式及 SVG 圖片,將 SVG?圖片中提取字符內(nèi)容,映射到網(wǎng)頁元素中,由于不能直接通過網(wǎng)頁元素直接提取數(shù)據(jù),所以起到了反爬的目的
目標對象:
aHR0cDovL3d3dy5wb3J0ZXJzLnZpcC9jb25mdXNpb24vZm9vZC5odG1s
1、分析
打開目標頁面,查看頁面中電話號碼的網(wǎng)頁元素
我們發(fā)現(xiàn),電話號碼中的每一個數(shù)字都對應一個 d 標簽,d 標簽中的 class 屬性值都是以「 vhk 」開頭的

查看右側(cè) Styles 樣式標簽后,發(fā)現(xiàn)上面匹配的 d 標簽的背景圖片「?background-image 」被設置為一張 SVG?圖片,d 標簽的寬度固定為 14px,高度為 30px
在樣式「?vhkbvu 」中,通過定義 background_position 指定背景圖片的移動方向,比如:圖中相當于背景圖片向左移動 386px,向上移動 97px

然后,我們查看 svg 圖片的源文件
字體大小為 14px,顏色值為 #666
4 個 text 標簽代表 4 行數(shù)字
4 行數(shù)字對應的 y 軸坐標值固定為 38、83、120、164
<svg?xmlns="http://www.w3.org/2000/svg"?version="1.1"?xmlns:xlink="http://www.w3.org/1999/xlink"?width="650px"?height="230.0px">
<style>text?{font-family:PingFangSC-Regular,Microsoft?YaHei,'Hiragino?Sans?GB',Helvetica;font-size:14px;fill:#666;}style>
????<text?x="14?28?42?56?70?84?98?112?126?140?154?168?182?196?210?224?238?252?266?280?294?308?322?336?350?364?378?392?406?420?434?448?462?476?490?504?518?532?546?560?574?588?602?616?630?644?658?672?686?700?714?728?742?756?770?784?798?812?826?840?854?868?882?896?910?924?938?952?966?980?994?1008?1022?1036?1050?1064?1078?1092?1106?1120?1134?1148?1162?1176?1190?1204?1218?1232?1246?1260?1274?1288?1302?1316?1330?1344?1358?1372?1386?1400?1414?1428?1442?1456?1470?1484?1498?1512?1526?1540?1554?1568?1582?1596?1610?1624?1638?1652?1666?1680?1694?1708?1722?1736?1750?1764?1778?1792?1806?1820?1834?1848?1862?1876?1890?1904?1918?1932?1946?1960?1974?1988?2002?2016?2030?2044?2058?2072?2086?2100?"?y="38">154669136497975167479825383996313925720573text>
????<text?x="14?28?42?56?70?84?98?112?126?140?154?168?182?196?210?224?238?252?266?280?294?308?322?336?350?364?378?392?406?420?434?448?462?476?490?504?518?532?546?560?574?588?602?616?630?644?658?672?686?700?714?728?742?756?770?784?798?812?826?840?854?868?882?896?910?924?938?952?966?980?994?1008?1022?1036?1050?1064?1078?1092?1106?1120?1134?1148?1162?1176?1190?1204?1218?1232?1246?1260?1274?1288?1302?1316?1330?1344?1358?1372?1386?1400?1414?1428?1442?1456?1470?1484?1498?1512?1526?1540?1554?1568?1582?1596?1610?1624?1638?1652?1666?1680?1694?1708?1722?1736?1750?1764?1778?1792?1806?1820?1834?1848?1862?1876?1890?1904?1918?1932?1946?1960?1974?1988?2002?2016?2030?2044?2058?2072?2086?2100?"?y="83">560862462805204755437571121437458524985017text>
????<text?x="14?28?42?56?70?84?98?112?126?140?154?168?182?196?210?224?238?252?266?280?294?308?322?336?350?364?378?392?406?420?434?448?462?476?490?504?518?532?546?560?574?588?602?616?630?644?658?672?686?700?714?728?742?756?770?784?798?812?826?840?854?868?882?896?910?924?938?952?966?980?994?1008?1022?1036?1050?1064?1078?1092?1106?1120?1134?1148?1162?1176?1190?1204?1218?1232?1246?1260?1274?1288?1302?1316?1330?1344?1358?1372?1386?1400?1414?1428?1442?1456?1470?1484?1498?1512?1526?1540?1554?1568?1582?1596?1610?1624?1638?1652?1666?1680?1694?1708?1722?1736?1750?1764?1778?1792?1806?1820?1834?1848?1862?1876?1890?1904?1918?1932?1946?1960?1974?1988?2002?2016?2030?2044?2058?2072?2086?2100?"?y="120">671260781104096663000892328440489239185923text>
????<text?x="14?28?42?56?70?84?98?112?126?140?154?168?182?196?210?224?238?252?266?280?294?308?322?336?350?364?378?392?406?420?434?448?462?476?490?504?518?532?546?560?574?588?602?616?630?644?658?672?686?700?714?728?742?756?770?784?798?812?826?840?854?868?882?896?910?924?938?952?966?980?994?1008?1022?1036?1050?1064?1078?1092?1106?1120?1134?1148?1162?1176?1190?1204?1218?1232?1246?1260?1274?1288?1302?1316?1330?1344?1358?1372?1386?1400?1414?1428?1442?1456?1470?1484?1498?1512?1526?1540?1554?1568?1582?1596?1610?1624?1638?1652?1666?1680?1694?1708?1722?1736?1750?1764?1778?1792?1806?1820?1834?1848?1862?1876?1890?1904?1918?1932?1946?1960?1974?1988?2002?2016?2030?2044?2058?2072?2086?2100?"?y="164">684431081139502796807382text>
svg>
因此,我們能得出一個結(jié)論,即:d 標簽通過 SVG 背景圖片,結(jié)合一定的偏移量 + 寬高度,從 SVG 圖片中固定一個數(shù)字展示在頁面上
2、實現(xiàn)
首先,我們獲取 SVG 圖片、CSS 樣式文件的源文件
PS:為了方便后面樣式的解析,需要將 CSS?樣式源碼的換行符和空格全部刪除掉
import?requests
...
def?start(self):
????????#?1、svg源文件
????????self.svg_source?=?requests.get("http://www.porters.vip/confusion/font/food.svg").text
????????#?2、css文件源文件
????????#?注意:將換行符、空格清除,方便下一步匹配
????????self.css_source?=?requests.get("http://www.porters.vip/confusion/css/food.css").text.replace('\n',?'').replace(
????????????'?',?'')
...
然后,使用正則表達式解析 SVG 圖片源文件,提取所有的 y 軸坐標及行數(shù)據(jù)列表
import?re
...
????def?parse_svg(self):
????????"""
????????解析svg文件
????????:return:
????????"""
????????#?獲取y軸值及數(shù)據(jù)
????????text_content?=?re.findall('y="(.*?)">(.*?)',?self.svg_source,?re.S)
????????#?print(text_content)
????????#?y軸值及行數(shù)據(jù)
????????return?[item[0]?for?item?in?text_content],?[item[1]?for?item?in?text_content]
...
數(shù)據(jù)格式如下:
#?y軸值列表及行數(shù)據(jù)值如下
#?y軸值列表
['38',?'83',?'120',?'164']
#?對應的行數(shù)據(jù)值列表
['154669136497975167479825383996313925720573',?'560862462805204755437571121437458524985017',?'671260781104096663000892328440489239185923',?'684431081139502796807382']
最后,遍歷要解析的樣式名,從?SVG 圖片中提取對應的數(shù)值
需要注意的是,SVG 圖片的文字大小固定為 14px,根據(jù)行內(nèi)容提取值時,只需要利用偏移量獲取索引值,最后拿到實際指向的數(shù)值即可
...
????def?get_number_from_svg(self,?style_name,?y_nums,?datas):
????????"""
????????獲取svg中實際的數(shù)據(jù)
????????:param?y_nums:?y軸坐標列表
????????:param?datas:?數(shù)據(jù)值列表
????????:return:
????????"""
????????#?使用正則表達式從樣式內(nèi)容中匹配x軸、y軸的偏移量(去除了換行符、空格),匹配正數(shù)字,\d+
????????deviation_x,?deviation_y?=?\
????????????re.compile('.%s{background:-(\d+)px-(\d+)px;}'?%?style_name).findall(self.css_source)[0]
????????#?獲取svg圖片中的y軸坐標
????????#?注意:這里取首次大于偏移量的y軸坐標,作為截取數(shù)據(jù)真實的y軸坐標
????????position_y?=?[y?for?y?in?y_nums?if?int(deviation_y)?<=?int(y)][0]
????????#?獲取y軸坐標的索引值,然后獲取該行的內(nèi)容
????????content?=?datas[y_nums.index(position_y)]
????????#?svg字體大小為14px,因此可以通過【偏移量/字體大小】拿到x軸的索引
????????x_index?=?int(int(deviation_x)?/?14)
????????#?通過內(nèi)容及索引,獲取實際截取的數(shù)字
????????return?str(content[x_index])
...以上就完成了對頁面中「 電話號碼 」的解析,我們只需要提取頁面元素中的樣式名,獲取映射的數(shù)值進行替換即可
我已經(jīng)將文章中的源碼上傳到后臺,回復關鍵字「 svgys 」即可以獲取完整的源碼
如果你覺得文章還不錯,請大家?點贊、分享、留言?下,因為這將是我持續(xù)輸出更多優(yōu)質(zhì)文章的最強動力!
END
