python房价数据分析统计服_Python 爬取分析全国 12 个城市 4 万条房价信息,告诉你该怎样买房?...
原標題:Python 爬取分析全國 12 個城市 4 萬條房價信息,告訴你該怎樣買房?
作者 | 月小水長
責編 | 伍杏玲通過分頁、線程池、代理池等技術,快速爬取鏈家網近4萬條在售二手房信息,速度可達 10000 條 / 5 分鐘。
通過對二手房作數據分析,得到北上廣深等(新)一線城市四地房價的縱向比較,同時對各個城市各個區的房價做橫向對比,并將對比結果可視化出來。
主要用到的庫或模塊包括 Requests、PyQuery、ThreadPoolExecutor、JSON、Matplotlib、PyEcharts。
環境:Widnows10、Python3.5、Pycharm2018。
數據抓取
爬蟲架構設計
通過分析鏈家網的 URL ,不難發現,每一個城市的鏈家網的基本格式是:
城市名簡拼 + ”.lianjia.com“
所以整個爬蟲最外層應該是遍歷一個保存城市簡拼的列表,拼接得到一個個起始 URL,根據這些 URL 爬取對應城市的鏈家網。
針對每一個城市的鏈家網而言,首先得到該城市在售二手房的總套數,由于每一頁顯示的套數是 30,由總套數整除以30再加上1可以得到總頁數,但是由于最大可瀏覽頁數為 100,所以我們這里得加個判斷,如果總頁數大于 100 的話,令總頁數等于 100。
分析具體城市的鏈家網每一頁的 URL, 以北京為例,我們可以發現第 N 頁的 URL 是:
bj.lianjia.com/ershoufang/pg{N},由此我們可以通過以下代碼來得到每一頁的 URL:
fori inrange(total_page):
page_url = "bj.lianjia.com/ershoufang/pg{}".format(i+1)
本來得到每一頁的 URL 后,我們可以得到該頁上 30 套房的房價信息和詳情頁 URL,但是頁面上沒有房子所在區的信息。
我們只能再向下請求訪問詳情頁 URL,從而提取出我們想要的所有數據。
綜上所述,我們可以將整個框架從上往下分為四層,如下圖所示:
基于上述思路,在寫代碼的時候,可以分層從上往下實現,方便調試。
第一層 & 第二層:獲取總套數
根據城市簡拼得到起始 URL,并得到總套數,為分頁做準備。
defget_list_page_url(city):
start_url = "https://{}.lianjia.com/ershoufang".format(city)
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36',
}
try:
response = requests.get(start_url, headers=headers)
# print(response.status_code, response.text)
doc = pq(response.text)
total_num = int(doc(".resultDes .total span").text())
total_page = total_num // 30+ 1
# 只能訪問到前一百頁
iftotal_page > 100:
total_page = 100
page_url_list = list()
fori inrange(total_page):
url = start_url + "/pg"+ str(i + 1) + "/"
page_url_list.append(url)
#print(url)
returnpage_url_list
except:
print("獲取總套數出錯,請確認起始URL是否正確")
returnNone
第三層:根據起始 URL 得到分頁 URL
defget_detail_page_url(page_url):
globaldetail_list
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36',
'Referer': 'https://bj.lianjia.com/ershoufang'
}
try:
response = requests.get(page_url,headers=headers,timeout=3)
doc = pq(response.text)
i = 0
detail_urls = list()
foritem indoc(".sellListContent li").items():
i += 1
print(i)
ifi == 31:
break
child_item = item(".noresultRecommend")
ifchild_item == None:
i -= 1
detail_url = child_item.attr("href")
detail_urls.append(detail_url)
returndetail_urls
except:
print("獲取列表頁"+ page_url + "出錯")
第四層
本層做的是具體解析,解析使用的是 PyQuery 庫,支持 CSS 選擇器且比 Beautiful Soup 方便。僅僅需要下面幾行代碼就幫助我們獲得了目標數據:
response= requests.get(url=detail_url, headers=headers, proxies=proxies)
#detail_url 是得到的詳情頁 URL
detail_dict= dict()
doc= pq(response.text)
unit_price= doc(".unitPriceValue").text()
unit_price= unit_price[0:unit_price.index("元")]
title= doc("h1").text()
area= doc(".areaName .info a").eq(0).text().strip()
url= detail_url
多線程爬取
由于待爬取的數據量巨大,使用單線程速度太慢,最開始采用了第三方庫 ThreadPool 來實現多線程,后來了解到 Python3.5 的內置包 concurrent.futures,使用里面的 ThreadPoolExecutor 來實現多線程,速度又提升了 20% 以上。
p = ThreadPoolExecutor(30)
forpage_url inpage_url_list:
p.submit(get_detail_page_url, page_url).add_done_callback(detail_page_parser)
p.shutdown()
第 1 行通過構造函數新建了線程池對象,最大可并發線程數指定為 30,如不指定,其默認值是 CPU 數的 5 倍,第 2、3 行依次把爬取的任務提交到線程池中,并設置回調函數,這里的回調函數拿到的是一包含 get_detail_page_url 返回值的對象。
并把這個對象作為回調函數的參數 res,先把返回的res得到一個結果,即在前面加上一個res.result(),這個結果就是 get_detail_page_url 的返回值。
IP 代理池
由于爬取的數量大,同時由于多線程提高了速度,鏈家網會拒絕訪問,這時可通過代理 IP 來訪問,這里使用已經有的輪子,源碼鏈接附在文末。
下載后新開一個 Pycharm 視窗運行該項目,然后我們可以用下面的方式來獲取可用的代理 IP:
defget_valid_ip():
url = "http://localhost:5000/get"
try:
ip = requests.get(url).text
returnip
except:
print("請先運行代理池")
然后通過參數設置使用代理 IP:
proxies = {
"http": "http://"+ get_valid_ip(),
}
response = requests.get(url=detail_url, headers=headers, proxies=proxies)
數據保存
采用 JSON文件形式保存數據,每個城市保存一個 JSON文件,文件名為該城市簡拼。
defsave_data(data,filename):
withopen(filename+".json", 'w', encoding="utf-8") asf:
f.write(json.dumps(data, indent=2, ensure_ascii=False))
稍等一會兒,所有數據就保存在本地了:
本爬蟲所爬數據僅為本人測試,嚴禁商用。
數據分析
數據整合
在這里做一些求同地區房價最大值、最小值、平均值,以及數據格式統一化的工作:
def split_data():
global region_data
region_data = dict()
for region in dic_data.keys():
# 最大值、最小值、平均值
region_data[region] = {"max":dic_data[region][0],"min":dic_data[region][0],"average":0}
for per_price in dic_data[region]:
if per_price > region_data[region]["max"]:
region_data[region]["max"] = per_price
if per_price < region_data[region]["min"]:
region_data[region]["min"] = per_price
region_data[region]["average"] += per_price
region_data[region]["average"] /= len(dic_data[region])
# 保留兩位小數
region_data[region]["average"] = round(region_data[region]["average"],2)
數據可視化
將分析結果通過 Matplotlib 直觀的體現出來,該部分的代碼如下:
defdata_viewer():
label_list = region_data.keys() # 橫坐標刻度顯示值
max = []
min = []
average = []
forlabel inlabel_list:
max.append(region_data[label].get("max"))
min.append(region_data[label].get("min"))
average.append(region_data[label].get("average"))
x = range(len(max))
"""
繪制條形圖
left: 長條形中點橫坐標
height: 長條形高度
width: 長條形寬度,默認值0
.8
label: 為后面設置legend準備
"""
rects1 = plt.bar(x=x, height=max, width=0.25, alpha=0.8, color='red', label="最大值")
rects2 = plt.bar(x=[i + 0.25fori inx], height=average, width=0.25, color='green', label="平均值")
rects3 = plt.bar(x=[i + 0.5fori inx], height=min, width=0.25, color='blue', label="最小值")
#plt.ylim(0, 50) # y軸取值范圍
plt.ylabel("房價/元")
"""
設置x軸刻度顯示值
參數一:中點坐標
參數二:顯示值
"""
plt.xticks([index + 0.2forindex inx], label_list)
plt.xlabel("地區")
plt.legend()
forrect inrects1:
height = rect.get_height()
plt.text(rect.get_x() + rect.get_width() / 2, height+1, str(height), ha="center", va="bottom")
forrect inrects2:
height = rect.get_height()
plt.text(rect.get_x() + rect.get_width() / 2, height + 1, str(height), ha="center", va="bottom")
forrect inrects3:
height = rect.get_height()
plt.text(rect.get_x() + rect.get_width() / 2, height + 1, str(height), ha="center", va="bottom")
plt.show()
結果如下:
限于篇幅,其他城市的圖就不放了。
再來看全國主要一線城市二手房房價有序條形圖:
可以看出,北京、上海、深圳的房價大致在同一水平線,而廈門位于第四,廣州在第六,最后看一下房價地域圖:
最后看一下房價地域圖這是基于 Java 的可交互動態圖,放截圖挺別扭的,我已經把它放在我的網上了,感興趣的可以點擊在線觀看。
作者簡介:月小水長,某 985 計算機學院在校生,熟悉 C++、Java、Python 等多種語言,有大型軟件項目開發經驗,致力于安卓、計算機視覺、爬蟲、數據可視化開發,同時也是業余的前端愛好者。
微信公眾號:inspurer
源碼:https://github.com/Python3Spiders/LianJiaSpider.git
動態圖展示:https://inspurer.github.io/fang_price_city.html
責任編輯:
總結
以上是生活随笔為你收集整理的python房价数据分析统计服_Python 爬取分析全国 12 个城市 4 万条房价信息,告诉你该怎样买房?...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 电视剧《猎毒人》观后感
- 下一篇: ethereumjs/ethereumj