在知乎上看到了一個提問,大概意思是使用xpath爲什麼無法獲取到租房價格信息。問題的鏈接在這裏:
看到問題,我也以爲很好解決,想着很快寫完答案就結束了。結果發現自己是too young too simple。要爬取的網址來自 自如租房。
開始解答這個問題,如下:
看到你這問題 本來想介紹一下xpath,結果發現自己 too young too simple。看樣子自如爲了反爬竟然用上了雪碧圖來顯示價格,而且最關鍵的是 這個雪碧圖中數字的顯示順序是隨機的,每次刷新都會換一張圖。
什麼是雪碧圖
什麼是雪碧圖?簡單說來就是通過把所有圖片合成一張大圖,然後以移位方式展示圖片其中的某一部分。雪碧圖的好處就不說了。而且自如用雪碧圖的目的也只是爲了反爬。
來具體看看雪碧圖的工作原理,我們就來看下自如用來顯示價格的這張雪碧圖,如下:
所有的數字都合在一張圖上。
價格展示
那麼爲了展示價格要怎麼做呢,前端代碼怎麼寫呢?
HTML 部分,如下:
<p value="" class="price">
<span style="background-position:1000px" class="num rmb">¥</span>
<span style="background-position:-240px" class="num"></span>
<span style="background-position:-210px" class="num"></span>
<span style="background-position:-150px" class="num"></span>
<span style="background-position:-210px" class="num"></span>
<span class="gray-6"> (每月)</span>
</p>
主要是通過css設置background-position設置圖片移位顯示不同的數字。
說是雪碧圖呢?這裏沒有設置圖片的代碼啊。接着看下CSS部分,如下:
body.ratio2 .price span.num {
background-size: auto 30px;
background-image: url(//static8.ziroom.com/phoenix/pc/images/price/e05092a2f84c9cca5e4d881535072ae1.png);
}
background-image設置顯示的背景圖片。我們可以把其中的url截取出來,然後加上 http 的前綴,如下:
http://static8.ziroom.com/pho...
訪問該地址,便會得到與開頭類似的圖片,如下:
注:不知道這些圖片是否會被經常清理,如果查看該回答時是不能打開該圖,可以去自如的網站重新查看。
那麼有該圖,價格怎麼顯示?這就是html中內嵌的css起作用了。再看顯示價格的html代碼:
<p value="" class="price">
<span style="background-position:1000px" class="num rmb">¥</span>
<span style="background-position:-240px" class="num"></span>
<span style="background-position:-210px" class="num"></span>
<span style="background-position:-150px" class="num"></span>
<span style="background-position:-210px" class="num"></span>
<span class="gray-6"> (每月)</span>
</p>
可以先來看一下,上面這段代碼展示的頁面是什麼樣子的?如下:
展示的價格是2090,然後繼續看下雪碧圖中數字的順序、html代碼中background-position以及css圖片展示大小(30px),就可以推出,顯示數字與background-position的關係是:
0px 1
-30px 7
-60px 4
-90px 3
-120px 5
-150px 9
-180px 8
-210px 0
-240px 2
-270px 6
代碼實現
如果雪碧圖是固定不變的,我們就可以寫出類似下面的代碼 :
position_text_map = {
"background-position:0px": 1,
"background-position:-30px": 7,
"background-position:-60px": 4,
"background-position:-90px": 3,
"background-position:-120px": 5,
"background-position:-150px": 9,
"background-position:-180px": 8,
"background-position:-210px": 0,
"background-position:-240px": 2,
"background-position:-270px": 6
}
price = 0
for span_selector in price_selector.xpath("/span[@class='num']"):
position = span_selector.xpath('//div/@style')[0]
price = price * 10 + position_text_map[position]
print(price)
到此便可計算出最終價格。
隨機順序
但是,我要非常可以可惜的是一句,沒這麼簡單,雪碧圖每次都是隨機生成的,所以只有網站知道每個position對應的數字是多少,而我們卻無法得知。
那麼,沒有辦法解決了嗎?當然不是,此時就需要用到ocr技術了,即圖片轉文字。這裏需要慶幸的是,價格需人眼好識別,所以沒有驗證碼那麼千奇百怪。我們可以從github找一些解決方案。
比如使用tesseract,提供了一套圖片文字識別的解決方案。github如下:
同樣我們也可以找到它對應的python封裝:
只要我們成功識別出了雪碧圖中數字的順序,下面的事情就很好辦了。
總結
簡單來說,其實就是把價格上每個數字轉化圖片展示。而其中用的一個重要技術就是雪碧圖。通過這種方式就可以把具體的文字轉化爲相應的css,類似於某種加密效果。最終就實現了反爬。