python爬取自如數據 原

前言

學習python有一小段時間了,爬蟲也看了一些,所以想拿個簡單點的練一下手,而且最近碰上自如比較火,這裏就用自如來練手把

分析

鏈接:http://www.ziroom.com/z/nl/z3.html

上面那個是自如北京的搜索頁面,按照我的理解,所有的房源和一些基本信息應該都可以從這個頁面得來(自如宅是自如自己的廣告,不是我們需要的),這些都是頁面看到的信息,還有一個信息我們其實也可以拿下來,用於以後如果有需要的時候用,就是每一個房源的詳細頁面鏈接

然後我們看到其實鏈接都是固定套路,不一樣的只是後面那串數子,我猜就是數據庫保存的主鍵了,那麼我們也就可以開始準備我們自己的數據格式了(我這裏是保存在mysql的)

CREATE TABLE `beijing` (
  `id` int(10) NOT NULL AUTO_INCREMENT COMMENT '主鍵id',
  `price` int(10) NOT NULL DEFAULT '0' COMMENT '價格',
  `size` decimal(10,2) DEFAULT '0.00' COMMENT '大小',
  `floor` int(10) NOT NULL DEFAULT '0' COMMENT '樓層',
  `total_floor` int(10) NOT NULL DEFAULT '0' COMMENT '總樓層',
  `room` int(10) NOT NULL DEFAULT '0' COMMENT '房',
  `hall` int(10) NOT NULL DEFAULT '0' COMMENT '廳',
  `line` varchar(20) NOT NULL DEFAULT '' COMMENT '幾號線',
  `station` varchar(20) NOT NULL DEFAULT '' COMMENT '地鐵站',
  `distance` int(10) NOT NULL DEFAULT '0' COMMENT '距離',
  `taps` varchar(200) NOT NULL DEFAULT '' COMMENT '標籤',
  `href` varchar(100) NOT NULL DEFAULT '' COMMENT '鏈接',
  `address` varchar(100) NOT NULL DEFAULT '' COMMENT '附近地址',
  `area` varchar(20) NOT NULL DEFAULT '' COMMENT '區',
  `phase` varchar(20) NOT NULL DEFAULT '' COMMENT '收費週期',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;

接下來我們就開始分析頁面,首先我發現,點擊分頁2的時候,url改變了

http://www.ziroom.com/z/nl/z3.html?p=2 很簡單,只是一個普通的p來控制,但是這個會有一個問題,就是我們看全部的這個頁的時候,發現只有50頁,後面的數據就出不來了,北京的房源實際是不止那麼少的,我就去點了另外一個鏈接

http://www.ziroom.com/z/nl/z3-d23008614.html

出現了只有13頁,是不是說,每個標籤的全部下面都不會超過50的分頁,我們只需要去拿這些鏈接下面的數據就可以了呢,然後我就點了朝陽區下面的全部的這個鏈接,發現頁數也是50,也就是說,我們不能拿這個標籤,還需要再細一級,拿每一個區域下面的每一個標籤(不拿全部的這個標籤,因爲數據這樣就重複了),拿這些標籤是在zindex6下面的ul下的每一個li的第三個span開始一直到最後的一個span裏面的a變遷的href的屬性

r = requests.get(self.url)
    bsObj = BeautifulSoup(r.text, 'lxml')
    lis = bsObj.select('.zIndex6 ul li')
    for li in lis[1:]:
        hs = li.select('span')[2:]
        for h in hs:
            # 這個就是了
            href = 'http:' + h.select('a')[0].attrs.get('href')

這裏,我們拿到了每一個頁面,我們還需要知道這個頁面有多少分頁,好方便我們去循環

bsObj = self.get_html(url)
page_str = bsObj.find(string=re.compile('共([0-9]*)頁'))
page = re.search('共([0-9]*)頁', page_str).group(1)

接下來我們是不是就可以開始抓取了呢,不是的,其實還有一個問題,我們看價格

它的價格既不是文本,也不是圖片,而是用css來控制的,怎麼控制

我們找到這個css後面的背景圖,發現是一個類似雪碧圖的東西

而剛剛那個價格是怎麼來的,2130,

2對應的位移是270,在雪碧圖的最第十個(index=9),1對應的位移是30,在雪碧圖的第二個(index=1),3對應的位置是60,在雪碧圖的第三個

我們已經找到規律了

i = re.search('background-position:-([0-9]*)px', style).group(1)
k = int(int(i) / 30)
// code爲雪碧圖的數字
price_str += code[k:k + 1]

那麼是不是我們這個圖的數字排序是固定的,我們打開另外一個鏈接,發現不是的,這個圖片是隨機生成的,也就是說,我們沒打開一個鏈接,都是不一樣的,那麼要怎麼找到這個圖片呢,看源碼,我們發現這麼一個js

<script>
var offset_unit = 30;        
if(window.devicePixelRatio >1){
    $('body').addClass('ratio2');
}
var ROOM_PRICE = {"image":"//static8.ziroom.com/phoenix/pc/images/price/b7944d44332aca7b65a0df428ec83cads.png","offset":[[9,1,2,6],[9,5,4,6],[1,7,4,6],[1,7,4,6],[9,2,4,6],[9,9,4,6],[9,9,4,6],[1,7,8,6],[9,1,2,6],[9,7,8,6],[5,6,8,6],[8,6,8,6],[9,3,2,6],[9,8,2,6],[9,5,2,6],[9,8,8,6],[8,6,4,6],[9,6,4,6]]};


$('#houseList p.price').each(function(i){
	var dom = $(this);
	if(!ROOM_PRICE['offset'] || !ROOM_PRICE['offset'][i]) return ;
	var pos = ROOM_PRICE['offset'][i];
	for(i in pos){
		var inx = pos.length -i -1;
		var seg = $('<span>', {'style':'background-position:-'+(pos[inx]*offset_unit)+'px', 'class':'num'});
		dom.prepend(seg);
	}
	var seg = $('<span>', {'style':'background-position:1000px', 'class':'num rmb'}).html('¥');
	dom.prepend(seg);
});
</script>

這個圖片的鏈接就在這裏,我們需要提取出來

js_str = bsObj.find(string=re.compile("//static8.ziroom.com/phoenix/pc/images/price/(.*).png"))
img_url = 'http:' + re.search('//static8.ziroom.com/phoenix/pc/images/price/(.*).png', js_str).group(0)

拿出來以後,我們還需要藉助一個工具來識別出來這個數字是怎樣的,下載下來放在一個地方,這樣我們就得到了這個數字了,

path = './code.png'
urllib.request.urlretrieve(img_url, path)
image = Image.open(path)
code = pytesseract.image_to_string(image, config='--psm 6')

這樣,我們就可以按照這個邏輯來一步一步的完成這個爬取,最後源碼放在了GitHub,需要的自取合適的城市

https://github.com/gcdong/ziroom

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章