此次我們要練手的網(wǎng)站是自如租房,自如租房網(wǎng)對(duì)租房的價(jià)格進(jìn)行了CSS背景圖片反爬,它把一張有隨機(jī)0-9數(shù)字的圖片作為背景圖片,然后通過(guò)background-position樣式來(lái)映射數(shù)字,我們需要找到背景反爬的規(guī)律以及通過(guò)OCR識(shí)別出背景圖片中的數(shù)字。
目標(biāo)分析

頁(yè)面效果
可以發(fā)現(xiàn)同一個(gè)背景位置偏移量對(duì)應(yīng)的映射的價(jià)格數(shù)字是一樣的,而且行內(nèi)樣式里有背景圖片的鏈接,并且
background-size是20px,我們下載背景圖片然后分析背景圖片與背景位置偏移量的映射關(guān)系:
背景圖片大小

背景圖片
可以發(fā)現(xiàn)圖片大小是
300x28,圖片里的數(shù)字是8670415923,我們首先需要把圖片的寬度等比例縮小到20px,縮放后得到的規(guī)格是214.281x20,每個(gè)數(shù)字的大小214.281/10 = 21.4281,保留一位小數(shù)就是21.4px,再看網(wǎng)頁(yè)源代碼上的背景偏移量數(shù)字2的偏移量是-171.2px,171.2/21.4 = 8 因?yàn)榈谝粋€(gè)是的偏移量為0,所以數(shù)字2對(duì)應(yīng)的應(yīng)該是8+1 = 9 ,映射到圖片上第9個(gè)數(shù)字,我們發(fā)現(xiàn)正是數(shù)字2,數(shù)字5和數(shù)字0的背景偏移量分別是-128.4px和-64.2px,128.4/21.4 +1 = 7以及64.2/21.4 +1 = 4,映射到圖片上第7個(gè)數(shù)字和第4個(gè)數(shù)字,我們發(fā)現(xiàn)正是數(shù)字5和數(shù)字0,找到了背景反爬偏移量的映射規(guī)律,我們需要識(shí)別背景圖片里的數(shù)字,我們可以使用Tesseract來(lái)識(shí)別,背景圖片里的數(shù)字沒(méi)有干擾線以及噪點(diǎn)所以識(shí)別出來(lái)基本上是100%準(zhǔn)確率。
破解思路
先下載背景圖片,用Tesseract來(lái)識(shí)別背景圖片里的數(shù)字,再提取網(wǎng)頁(yè)源代碼中背景圖片的偏移量,最后根據(jù)我們得出的規(guī)律計(jì)算出正確的數(shù)字。
'''
時(shí)間原因只抓1頁(yè)
'''
import requests
from urllib.request import urlretrieve
import re
import pytesseract
from PIL import Image
from lxml import etree
# 請(qǐng)求的url
url = "http://sz.ziroom.com/z/"
headers = {
'user-agent': "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36",
}
response = requests.get(url, headers=headers)
html = etree.HTML(response.text)
bg_img_info = html.xpath('//div[@class="price"]/span[@class="num"]/@style')[0]
if len(re.findall(r'background-image: url\((.*?)\)',bg_img_info))>0:
bg_img_url = "http:" + re.findall(r'background-image: url\((.*?)\)',bg_img_info)[0]
info = html.xpath('//div[@class="Z_list-box"]/div[@class="item"]')
for i in info:
title = i.xpath('.//h5/a/text()')[0]
area = i.xpath('.//div[@class="desc"]/div[1]/text()')[0]
location = i.xpath('.//div[@class="desc"]/div[@class="location"]/text()')[0].replace('\n',"").replace('\t',"").replace(' ',"")
tag = ",".join(i.xpath('.//div[@class="tag"]/span/text()'))
position_list = [re.findall(r'background-position: -(.*?)px',j)[0] for j in i.xpath('.//div[@class="price"]/span[@class="num"]/@style')]
price_list = [int(float(i)/21.4 + 1) for i in position_list]
urlretrieve(bg_img_url,'background_img.png')
image = Image.open('background_img.png')
text = pytesseract.image_to_string(image)
num = [i for i in text]
price = "¥" + "".join([num[i-1] for i in price_list]) + "/月起"
print(title, area, location, tag,price)
else:
print("提取背景圖片鏈接出錯(cuò)!")
結(jié)果

運(yùn)行結(jié)果