1. 程式人生 > >爬取兩萬多條租房資料,算算在廣州你能「活到」第幾集?

爬取兩萬多條租房資料,算算在廣州你能「活到」第幾集?

640?wx_fmt=gif

640?wx_fmt=jpeg

作者 | zone7

責編 | 仲培藝

此前,筆者曾用 Python 爬取 1.7 萬條租房資料,並據此撰文揭示了深圳房價飆升背後的生存壓力。此番再析廣州租房價格現狀,在升級爬蟲技術之餘,也完善了更多細節,原始碼頗值細細探究。此次分析採集了廣州 11 個區,23339 條資料,如下圖:

640

樣本資料

其中後半部分地區資料量偏少,是由於該區房源確實不足。因此,此次調查也並非非常準確,權且當個娛樂專案,供大家觀賞。


640?wx_fmt=png

統計結果


我們且先看統計結果,然後再看技術分析。廣州房源分佈如下(按區劃分),其中天河佔據了大部分房源,但這塊地的房租可謂不菲。

640

房源分佈

房租單價(每月每平方米單價 -- 平均數)

即 1 平方米 1 個月的價格。方塊越大,代表價格越高。

640

房租單價:平方米/月

可以看出天河、越秀、海珠都越過了 50 大關,分別是 75.042 、64.249、59.621 ,是其他地區的幾倍。

如果在天河租個 20 平方的房間:

75.042 x 20 = 1500.84

再來個兩百的水電、物業:

1500.84 + 200 = 1700.84

我們按正常生活來算的話,每天早餐 10 塊,中午 15 塊,晚飯 15 塊:

1700.84 + 40 x 30 = 2700.84

那麼平時的日常生活需要 2700.84 塊。

隔斷時間下個館子,每個月買些衣服,交通費,談個女朋友,與女朋友出去逛街,妥妥滴加個 2500:

2700.84 + 2500 = 5200.84

給爸媽一人一千:

5200.84 + 2000 = 7200.84

月薪一萬還是有點存款的,比深圳好一點,但是可能廣州的薪資就沒有深圳那麼高了。

房租單價:(每日每平方米單價 -- 平均數)

即 1 平方米 1 天的價格。

640

租房單價:平方米/日

哈哈,感受一下寸土寸金的感覺。[捂臉]

640?wx_fmt=gif

崩潰


戶型

戶型主要以 3 室 2 廳與 2 室 2 廳為主。與小夥伴抱團租房是最好的選擇了,不然與不認識的人一起合租,可能會發生一系列讓你不舒服的事情。字型越大,代表戶型數量越多。

640

戶型

640

戶型

租房面積統計

其中 30 - 90 平方米的租房佔大多數,如今之計,也只能是幾個小夥伴一起租房,抱團取暖了。

640

租房面積統計

租房描述詞雲

這是爬取的租房描述,其中字型越大,標識出現的次數越多。其中【住家、全套、豪華、齊全】佔據了很大的部分,說明配套設施都是挺齊全的。

640

租房描述


640?wx_fmt=png

爬蟲技術分析和程式碼實現


爬蟲涉及到的技術工具如下:

  • 請求庫:scrapy、requests

  • HTML 解析:BeautifulSoup

  • 詞雲:wordcloud

  • 資料視覺化:pyecharts

  • 資料庫:MongoDB

  • 資料庫連線:pymongo

爬蟲程式碼實現

跟上一篇文章不一樣,此次使用了 scrapy 爬蟲框架來爬取資料,各個方面也進行了優化,例如:自動生成各個頁面的地址。

由於房某下各個區域的首頁地址和首頁以外的地址形式不一樣,但又有一定的規律,所以需要拼接各個部分的地址。

首頁地址案例:

# 第一頁
http://gz.zu.fang.com/house-a073/

非首頁地址:

# 第二頁
http://gz.zu.fang.com/house-a073/i32/
# 第三頁
http://gz.zu.fang.com/house-a073/i33/
# 第四頁
http://gz.zu.fang.com/house-a073/i34/


640


640

先解析首頁 url:

def head_url_callback(self, response):
    soup = BeautifulSoup(response.body, "html5lib")
    dl = soup.find_all("dl", attrs={"id""rentid_D04_01"})  # 獲取各地區的 url 地址的 dl 標籤
    my_as = dl[0].find_all("a")  # 獲取 dl 標籤中所有的 a 標籤,
    for my_a in my_as:
        if my_a.text == "不限":  # 不限地區的,特殊處理
            self.headUrlList.append(self.baseUrl)
            self.allUrlList.append(self.baseUrl)
            continue
        if "周邊" in my_a.text:  # 清除周邊地區的資料
            continue
        # print(my_a["href"])
        # print(my_a.text)
        self.allUrlList.append(self.baseUrl + my_a["href"])
        self.headUrlList.append(self.baseUrl + my_a["href"])
    print(self.allUrlList)
    url = self.headUrlList.pop(0)
    yield Request(url, callback=self.all_url_callback, dont_filter=True)

再解析非首頁 url:

這裡先獲取到各個地區一共有多少頁,才能拼接具體的頁面地址。

640
# 再根據頭部 url 拼接其他頁碼的url
def all_url_callback(self, response): # 解析並拼接所有需要爬取的 url 地址
    soup = BeautifulSoup(response.body, "html5lib")
    div = soup.find_all("div", attrs={"id""rentid_D10_01"})  # 獲取各地區的 url 地址的 dl 標籤
    span = div[0].find_all("span")  # 獲取 dl 標籤中所有的 span 標籤,
    span_text = span[0].text
    for index in range(int(span_text[1:len(span_text) - 1])):
        if index == 0:
            pass
            # self.allUrlList.append(self.baseUrl + my_a["href"])
        else:
            if self.baseUrl == response.url:
                self.allUrlList.append(response.url + "house/i3" + str(index + 1) + "/")
                continue
            self.allUrlList.append(response.url + "i3" + str(index + 1) + "/")
    if len(self.headUrlList) == 0:
        url = self.allUrlList.pop(0)
        yield Request(url, callback=self.parse, dont_filter=True)
    else:
        url = self.headUrlList.pop(0)
        yield Request(url, callback=self.all_url_callback, dont_filter=True)

最後解析一個頁面的資料:

def parse(self, response): # 解析一個頁面的資料
    self.logger.info("==========================")
    soup = BeautifulSoup(response.body, "html5lib")
    divs = soup.find_all("dd", attrs={"class""info rel"})  # 獲取需要爬取得 div
    for div in divs:
        ps = div.find_all("p")
        try:  # 捕獲異常,因為頁面中有些資料沒有被填寫完整,或者被插入了一條廣告,則會沒有相應的標籤,所以會報錯
            for index, p in enumerate(ps):  # 從原始碼中可以看出,每一條 p 標籤都有我們想要的資訊,故在此遍歷 p 標籤,
                text = p.text.strip()
                print(text)  # 輸出看看是否為我們想要的資訊
            roomMsg = ps[1].text.split("|")
            area = roomMsg[2].strip()[:len(roomMsg[2]) - 1]
            item = RenthousescrapyItem()
            item["title"] = ps[0].text.strip()
            item["rooms"] = roomMsg[1].strip()
            item["area"] = int(float(area))
            item["price"] = int(ps[len(ps) - 1].text.strip()[:len(ps[len(ps) - 1].text.strip()) - 3])
            item["address"] = ps[2].text.strip()
            item["traffic"] = ps[3].text.strip()
            if (self.baseUrl+"house/"in response.url: # 對不限區域的地方進行區分
                item["region"] = "不限"
            else:
                item["region"] = ps[2].text.strip()[:2]
            item["direction"] = roomMsg[3].strip()
            print(item)
            yield item
        except:
            print("糟糕,出現 exception")
            continue
    if len(self.allUrlList) != 0
        url = self.allUrlList.pop(0)
        yield Request(url, callback=self.parse, dont_filter=True)


640?wx_fmt=png

資料分析實現

這裡主要通過 pymongo 的一些聚合運算來進行統計,再結合相關的圖示庫,進行資料展示。

資料分析:

    # 求一個區的房租單價(平方米/元)
    def getAvgPrice(self, region):
        areaPinYin = self.getPinyin(region=region)
        collection = self.zfdb[areaPinYin]
        totalPrice = collection.aggregate([{'$group': {'_id''$region''total_price': {'$sum''$price'}}}])
        totalArea = collection.aggregate([{'$group': {'_id''$region''total_area': {'$sum''$area'}}}])
        totalPrice2 = list(totalPrice)[0]["total_price"]
        totalArea2 = list(totalArea)[0]["total_area"]
        return totalPrice2 / totalArea2

    # 獲取各個區 每個月一平方米需要多少錢
    def getTotalAvgPrice(self):
        totalAvgPriceList = []
        totalAvgPriceDirList = []
        for index, region in enumerate(self.getAreaList()):
            avgPrice = self.getAvgPrice(region)
            totalAvgPriceList.append(round(avgPrice, 3))
            totalAvgPriceDirList.append({"value": round(avgPrice, 3), "name": region + "  " + str(round(avgPrice, 3))})

        return totalAvgPriceDirList

    # 獲取各個區 每一天一平方米需要多少錢
    def getTotalAvgPricePerDay(self):
        totalAvgPriceList = []
        for index, region in enumerate(self.getAreaList()):
            avgPrice = self.getAvgPrice(region)
            totalAvgPriceList.append(round(avgPrice / 303))
        return (self.getAreaList(), totalAvgPriceList)

    # 獲取各區統計樣本數量
    def getAnalycisNum(self):
        analycisList = []
        for index, region in enumerate(self.getAreaList()):
            collection = self.zfdb[self.pinyinDir[region]]
            print(region)
            totalNum = collection.aggregate([{'$group': {'_id''''total_num': {'$sum'1}}}])
            totalNum2 = list(totalNum)[0]["total_num"]
            analycisList.append(totalNum2)
        return (self.getAreaList(), analycisList)

    # 獲取各個區的房源比重
    

相關推薦

租房資料算算廣州

作者 | zone7 責編 | 仲培藝 此前,筆者曾用 Python 爬取 1.7 萬條租房資料,並據此撰文揭示了深圳房價飆升背後的生存壓力。此番再析廣州租房價格現狀,在升級爬蟲技術之餘,也完善了更多細節,原始碼頗值細細探究。此次分析採集了廣州 11

Node.js 2小時驢媽媽8W+旅遊資料

問題 這個介面一個IP短時間訪問次數多了是需要驗證的,之後就是不能再訪問了。 1.按照作者的邏輯是每個地點,每個頁面都需要自己一個一個的取獲取,這個工作量是比較大的,而且介面訪問多了就不能訪問了。 2.百度地圖獲取經緯度。其實這個是不需要的。去哪兒的頁

利用BeautifulSoup我愛我家的租房資料

因為之前對BeautifulSoup一直不是很熟悉,剛好身邊的朋友同事在找房子,就想著能不能自己寫個爬蟲爬一下資料,因此就寫了這個爬蟲。基本都是邊看書邊寫的,不過也沒什麼好講的。直接粘程式碼了。

項目實戰!5篇好奇心日報文章適合小白練手的實戰案例!

microsoft 找到 用戶數 clas 復制 parse span 入門知識 soup Python的知識很多,基本的入門就有很多東西要學,還有各種合樣的庫要學習。很多同學學了一段時間,進展很慢,學了前面忘了後面!要麽就是揠苗助長找一些特別難的例子,結果太難了,失去信心

和採集趕集網租房資訊看過來~~

本文主要介紹“趕集出租房資訊採集爬蟲”(以下簡稱“趕集租房爬蟲”)的使用教程及注意事項。 趕集網二手房源資訊時效性很強,使用者基數龐大,資訊清晰明瞭,這些資訊蘊含著很高的商機,能實時的反應現階段某一地區的租房現狀和趨勢,那如何採集呢? 下面,教你如何使用“趕集租房爬蟲”在雲端採集和匯

微信好友的部分資料並將所有人的個性簽名製成詞雲圖哈哈~~~~

import itchat itchat.login() friends = itchat.get_friends(update=True)[0:] male = female = other = 0 for i in friends[1:]: sex = i[

用python爬蟲去哪兒4500個熱門景點看看國慶不去哪兒

前言:本文建議有一定Python基礎和前端(html,js)基礎的盆友閱讀。 金秋九月,丹桂飄香,在這秋高氣爽,陽光燦爛的收穫季節裡,我們送走了一個個暑假餘額耗盡哭著走向校園的孩籽們,又即將迎來一年一度偉大祖國母親的生日趴體(無心上班,迫不及待想為祖國母親

Python北京租房資料從6個維度揭穿房租瘋漲的祕密!!!

導讀:昨天還幻想海邊別墅的年輕人,今天可能開始對房租絕望了。         8月初,有網友在“水木論壇”發帖控訴長租公寓加價搶房引起關注。據說,一名業主打算出租自己位於天通苑的三居室,預期租金7500元/月,結果被二方中介互相擡價,

閒來無事!我了九一7視訊!身體是一天不如一天!

    一共有20929位上傳者為這77000個視訊做出了自己的貢獻,嗯,感謝他們。 首先上一張全站視訊名稱的的詞雲圖吧,因為種種原因從網站爬取下來的視訊名稱是英文的,懶得再改了。     另外還有 verifi

閒來無事!我了7視訊!身體是一天不如一天!

一共有20929位上傳者為這77000個視訊做出了自己的貢獻,嗯,感謝他們。 首先上一張全站視訊名稱的的詞雲圖吧,因為種種原因從網站爬取下來的視訊名稱是英文的,懶得再改了。 另外還有verification(認證)這個詞頻率很高,因為91的視訊講究在拍攝時證明是自己拍

乾貨(附原始碼) | b站評論分析9.7分的新番憑啥這麼火?

7月番《工作細胞》最終話在十一前放出。這部動漫在b站上評分高達9.7。除了口碑之外,熱度也居高不下,更值得關注的是連很多平時不關注動漫的小夥伴也加入了追番大軍。這次我們的目標是爬取b站上的所有短評進行分析,用資料說明為什麼這部動漫會如此受歡迎。 01 工作細胞 《工作細胞》

9.7評分的電影!知道是啥電影嗎?這部電影確實好看

作者:量化小白H 7月番《工作細胞》最終話在十一前放出。這部動漫在b站上評分高達9.7。除了口碑之外,熱度也居高不下,更值得關注的是連很多平時不關注動漫的小夥伴也加入了追番大軍。這次我們的目標是爬取b站上的所有短評進行分析,用資料說明為什麼這部動漫會如此受歡迎。 01工作細胞 《工作細胞

了 48048 評論資料解讀 9.3 分的《毒液》是否值得一看?

11月,由湯姆·哈迪主演的“毒液:致命守護者”在國內上映,依託漫威的光環以及演員們精湛的演技,這部動作科幻片在貓眼評分得到豆瓣7.4的評分,口碑和票房都高於大多數同期上映的其他影片。 所以週日的時候跟基友去電影院去看了這場正邪共生的電影,100多人的影院座無虛席,不過看完之後對比其他漫威作品

我用爬蟲下來91P**N七視訊發現...

今天開個車,帶大家通過資料認識下91P**n(以下簡稱91)這個網站。 之前一個假期學習了Python爬蟲,於是拿91試試手,發現91非常容易爬取,獲取頁面時只要使用cookies即可,於是果斷按照“收藏最多”排行榜爬下來全站77000條視訊,注意到網站上的視訊每天都是增長的,現在已經78000+了,我們忽

重複資料第一

使用分析函式row_number() over (partiion by ... order by ...)來進行分組編號,然後取分組標號值為1的記錄即可。目前主流的資料庫都有支援分析函式,很好用。 其中,partition by 是指定按哪些欄位進行分組,這些欄位值相同的

執行緒圖片網(分類儲存到資料夾)

import requests import re from bs4 import BeautifulSoup import os from lxml import etree from multiprocessing import Process,Pool #

鏈家租房資料資料處理進行視覺化分析

 lianjiaspider.py import asyncio import aiohttp import pandas as pd from lxml import etree class LianjiaSpider(object): def __init

Python 11 Java 程序員信息竟有這些重大發現!

工作 不可 猝死 技術 永遠 Go 工程 允許 src 一提到程序猿,我們的腦子裏就會出現這樣的畫面: 或者這樣的畫面: 心頭縈繞的字眼是:禿頭、猝死、眼鏡、黑白 T 恤、鋼鐵直男…… 而真實的程序猿們,是每天要和無數數據,以及數十種編程語言打交道。上能手握億萬數據面不改

Python爬蟲入門 | 5 小豬短租租房信息

圖片 交流 ffffff 信息 jpg http 而已 基本 mat 小豬短租是一個租房網站,上面有很多優質的民宿出租信息,下面我們以成都地區的租房信息為例,來嘗試爬取這些數據。 小豬短租(成都)頁面:http://cd.xiaozhu.com/1.爬取租房標題 按照慣例,

highcharts實現動態重新整理)組資料

(function () {(function () { (document).ready(function () { Highcharts.setOptions({ global: { useUTC: false } }); var char