SVG反爬蟲不同于字體反爬蟲,它巧妙的利用css 與 svg的關(guān)系,將字符映射到網(wǎng)頁中,看起來雖然正常,但是卻抓取不到有效內(nèi)容。本文帶你深入淺出,破了SVG反爬蟲的套路,學(xué)會之后,可應(yīng)用于某點評網(wǎng)。
一、初識SVG反爬:
為了防止面對監(jiān)獄編程,我在本地自己做了一個網(wǎng)頁用于爬蟲測試。任務(wù)是爬取票據(jù)中的產(chǎn)品價格信息,按照往常一樣審查元素定位目標(biāo)節(jié)點,但是發(fā)現(xiàn)事情并不簡單。
看圖:
¥符號后面并沒有我們想要的價格信息,而是四個d標(biāo)簽取而代之。隨便選中一個7,發(fā)現(xiàn)對應(yīng)的是屬性class=lhtqsc的d標(biāo)簽。
看css樣式:
有兩段描述這個標(biāo)簽的語句,第一段比較常規(guī),但是其中的
就有點奇怪,而第二段,描述的是background,它的值是兩個 大小值,單位px。
打開svg文件查看:
貌似是沒什么規(guī)律的數(shù)字
查看該頁面網(wǎng)頁源代碼,發(fā)現(xiàn)是張這樣的:
二、什么是SVG?
想要搞定SVG反爬蟲就得先搞清楚SVG:
SVG是一種基于xml用于描述矢量圖的圖形格式,由于矢量圖放大或縮寫都不會影響圖形的質(zhì)量,所以被較多的應(yīng)用在web站點與App中,常見的存在形式是圖標(biāo)。
編寫一個SVG文件:
為了方便,我們可以把要寫的svg,寫到html文件中,新建一個svg.html鍵入如下內(nèi)容:
瀏覽器打開如下:
其中:
很關(guān)鍵,這一行用text標(biāo)簽定義了一段文本,fill是文本顏色屬性,為紅色,并且指定了文本的坐標(biāo)。該坐標(biāo)的規(guī)則是:
- 以左上角為坐標(biāo)系的原點(0,0)
- X 軸的正方向向右,從 0,0 點開始向右, x 逐漸增大。Y 軸的正方向向下,從 0,0 點開始向下, y 逐漸增大。
- 坐標(biāo)以像素為單位
- n 個字符可以有 n 個位置參數(shù)。
增加一行:
這行代碼指定了前九個字符的位置,且指定了文本的顏色,y的值也增大到100,瀏覽器打開如下:
再次增加一行:
上圖可以看到,在不改變文本順序的情況下通過改變x中的值,讓第一個字符I和第四個字符o交換了位置。
三、SVG與CSS的聯(lián)系:
現(xiàn)在我們嘗試把css和svg聯(lián)系起來,更加深入的理解,方便我們做下一步抓取工作:在svg中,X軸正方向為從左到右,y軸的正方向是從上到下;在css中,X軸負(fù)數(shù)向右,Y軸是負(fù)數(shù)向下。一圖勝千言:
所以,CSS與SVG剛好相反。新建一個zhiliao.svg并鍵入:
我們在style中 定義了字符的風(fēng)格,大?。?4px),以及顏色(#666)。定義了每個字符所在的位置。
現(xiàn)在我們對第一個字符h進(jìn)行定位,
X軸計算法則:字符大小 / 2 + 字符的x軸起點位置參數(shù)
Y軸計算法則:(y 軸高度 - 字符 y 軸起點 - 字符大?。? 2 + 字符 y 軸起點位置參數(shù) + 字符大小數(shù)值的一半
也就是:
X = 14/2 + 0 = 7
Y = (30 - 0 - 14) / 2 + 0 + 14 / 2 = 15
svg中對應(yīng)的定位就是 x = 7 ,y = 15
css與svg相反,所以是 -7,-15現(xiàn)在
新建一個zhiliao.css文件,鍵入如下內(nèi)容:
新建一個demo.html,鍵入:
html中會引入css文件,css又會引入svg文件。通過d標(biāo)簽的class屬性值讀取css對應(yīng)的svg標(biāo)簽,完成對svg的映射。然后把demo.html拖到瀏覽器,可以看到:
字符h完完整整的被我們成功的映射出來了。
搞懂了這些,反爬就不是難事了,我們要做的是讓程序搞定這些。
四、Python抓取數(shù)據(jù):
回到剛才的目標(biāo)網(wǎng)站,開始實戰(zhàn)抓取。
1.獲取css樣式文件與svg文件內(nèi)容:
2.獲取匹配出class屬性值對應(yīng)css參數(shù),與字符大?。?/h5>
測試尋找class=lhtqsc的css對應(yīng)參數(shù)和字符大小,輸出如下:
打開對應(yīng)css與svg文件驗證:
一致,成功!
3.觀察svg文件:
這里有四個text標(biāo)簽,對應(yīng)四個文本,每個文本X軸都是從0開始,并且以14遞增Y軸不相同的,分別是 38, 83 , 120 ,164文本順序也有所不同。現(xiàn)在我們get這些數(shù)據(jù):
輸出:
到這一步,我們成功的分別取出了y的和text標(biāo)簽的四個值,并組成了列表。但是,這些元素 幾乎沒有和 [‘38’, ‘83’, ‘120’, ‘164’] 中有相等的,
這對于我們尋找text標(biāo)簽包含的文本值并不影響,我們找到最近接近的即可。我們?nèi)匀灰?class=lhtqsc為例子,尋找它最近的y值,從而找出是哪個text標(biāo)簽包含的值。完善我們的代碼:
輸出:
然后就可以利用切片的特性尋找到對應(yīng)的數(shù)值啦!
輸出 7,有圖為證:
驗證:我們打開網(wǎng)站,看看對應(yīng)的是不是數(shù)字7
到這里,就算成功了,是不是很簡單呢?跟我一起做一遍吧。