
Python 爬取北京二手房數(shù)據(jù),分析北漂族買得起房嗎? | 附完整源碼
房價高是北漂們一直關心的話題,本文就對北京的二手房數(shù)據(jù)進行了分析。
本文主要分為兩部分:Python爬取趕集網(wǎng)北京二手房數(shù)據(jù),R對爬取的二手房房價做線性回歸分析,適合剛剛接觸Python&R的同學們學習參考。
Python爬取趕集網(wǎng)北京二手房數(shù)據(jù)
入門爬蟲一個月,所以對每一個網(wǎng)站都使用了Xpath、Beautiful Soup、正則三種方法分別爬取,用于練習鞏固。數(shù)據(jù)來源如下:
Xpath爬?。?
這里主要解決運用Xpath如何判斷某些元素是否存在的問題,比如如果房屋沒有裝修信息,不加上判斷,某些元素不存在就會導致爬取中斷。
importrequests
fromlxmlimportetree
fromrequests.exceptionsimportRequestException
importmultiprocessing
importtime
headers={
'User-Agent':'Mozilla/5.0(WindowsNT10.0;WOW64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/55.0.2883.87Safari/537.36'}
defget_one_page(url):
try:
response=requests.get(url,headers=headers)
ifresponse.status_code==200:
returnresponse.text
returnNone
exceptRequestException:
returnNone
defparse_one_page(content):
selector=etree.HTML(content)
ALL=selector.xpath('//*[@id="f_mew_list"]/div[6]/div[1]/div[3]/div[1]/div')
fordivinALL:
yield{
'Name':div.xpath('dl/dd[1]/a/text()')[0],
'Type':div.xpath('dl/dd[2]/span[1]/text()')[0],
'Area':div.xpath('dl/dd[2]/span[3]/text()')[0],
'Towards':div.xpath('dl/dd[2]/span[5]/text()')[0],
'Floor':div.xpath('dl/dd[2]/span[7]/text()')[0].strip().replace('\n',""),
'Decorate':div.xpath('dl/dd[2]/span[9]/text()')[0],
#地址需要特殊處理一下
'Address':div.xpath('dl/dd[3]//text()')[1]+div.xpath('dl/dd[3]//text()')[3].replace('\n','')+div.xpath('dl/dd[3]//text()')[4].strip(),
'TotalPrice':div.xpath('dl/dd[5]/div[1]/span[1]/text()')[0]+div.xpath('dl/dd[5]/div[1]/span[2]/text()')[0],
'Price':div.xpath('dl/dd[5]/div[2]/text()')[0]
}
ifdiv['Name','Type','Area','Towards','Floor','Decorate','Address','TotalPrice','Price']==None:##這里加上判斷,如果其中一個元素為空,則輸出None
returnNone
exceptException:
defmain():
foriinrange(1,500):#這里設置爬取500頁數(shù)據(jù),在數(shù)據(jù)范圍內(nèi),大家可以自設置爬取的量
url='http://bj.ganji.com/fang5/o{}/'.format(i)
content=get_one_page(url)
print('第{}頁抓取完畢'.format(i))
fordivinparse_one_page(content):
print(div)
if__name__=='__main__':
main()
Beautiful Soup爬取:
importre
frombs4importBeautifulSoup
importcsv
headers={'User-Agent':'Mozilla/5.0(WindowsNT10.0;WOW64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/55.0.2883.87Safari/537.36'}
response=requests.get(url,headers=headers)
soup=BeautifulSoup(content,'html.parser')
items=soup.find('div',class_=re.compile('js-tips-list'))
fordivinitems.find_all('div',class_=re.compile('ershoufang-list')):
'Name':div.find('a',class_=re.compile('js-title')).text,
'Type':div.find('dd',class_=re.compile('size')).contents[1].text,#tag的.contents屬性可以將tag的子節(jié)點以列表的方式輸出
'Area':div.find('dd',class_=re.compile('size')).contents[5].text,
'Towards':div.find('dd',class_=re.compile('size')).contents[9].text,
'Floor':div.find('dd',class_=re.compile('size')).contents[13].text.replace('\n',''),
'Decorate':div.find('dd',class_=re.compile('size')).contents[17].text,
'Address':div.find('span',class_=re.compile('area')).text.strip().replace('','').replace('\n',''),
'TotalPrice':div.find('span',class_=re.compile('js-price')).text+div.find('span',class_=re.compile('yue')).text,
'Price':div.find('div',class_=re.compile('time')).text
#有一些二手房信息缺少部分信息,如:缺少裝修信息,或者缺少樓層信息,這時候需要加個判斷,不然爬取就會中斷。
ifdiv['Name','Type','Area','Towards','Floor','Decorate','Address','TotalPrice','Price']==None:
foriinrange(1,50):
withopen('Data.csv','a',newline='')asf:#Data.csv文件存儲的路徑,如果默認路徑就直接寫文件名即可。
fieldnames=['Name','Type','Area','Towards','Floor','Decorate','Address','TotalPrice','Price']
writer=csv.DictWriter(f,fieldnames=fieldnames)
writer.writeheader()
foriteminparse_one_page(content):
writer.writerow(item)
time.sleep(3)#設置爬取頻率,一開始我就是爬取的太猛,導致網(wǎng)頁需要驗證。
if__name__=='__main__':
正則爬?。何已芯苛撕镁?,還是沒有解決。
這一過程中容易遇見的問題有:
有一些房屋缺少部分信息,如缺少裝修信息,這個時候需要加一個判斷,如果不加判斷,爬取就會自動終止(我在這里跌了很大的坑)。
Data.csv知識點存儲文件路徑默認是工作目錄,關于Python中如何查看工作目錄:
importos
#查看pyhton的默認工作目錄
print(os.getcwd())
#修改時工作目錄
os.chdir('e:\\workpython')
#輸出工作目錄
e:\workpython
爬蟲打印的是字典形式,每個房屋信息都是一個字典,由于Python中excel相關庫是知識盲點,所以爬蟲的時候將字典循環(huán)直接寫入了CSV。
Pycharm中打印如下:
將字典循環(huán)直接寫入CSV效果如下:
很多初學者對于Address不知如何處理,這里強調(diào)一下Beautiful Soup 中.contents的用法,親身體會,我在這里花了好多時間才找到答案。
R對爬取的二手房房價做一般線性回歸分析
下面我們用R對抓取的趕集網(wǎng)北京二手房數(shù)據(jù)做一些簡單的分析。
數(shù)據(jù)的說明
Name:主要是商家的醒目標題,不具備分析參考意義
Type:臥室數(shù)、客廳數(shù)、衛(wèi)生間數(shù)
Area:面積(平方米)
Towards:朝向
Floor:樓層
Decorate:裝修情況,如精裝修、簡單裝修、毛坯房
Address:二手房的地址
TotalPrice:總價
Price:均價(元/平方米)
data<-read.csv("E://DataForR/RData/data.csv")
DATA<-data[,-c(1,7)]#將Name和Address兩列去掉
DATA[sample(1:nrow(DATA),size=10),]
#在爬取的時候加入了判斷,所以不知道爬取的數(shù)據(jù)中是否存在缺失值,這里檢查一下
colSums(is.na(DATA))
#這里將Type的臥室客廳和衛(wèi)生間分為三個不同的列
##這里需要注意,有一些房屋沒有客廳如:1室1衛(wèi)這時候需要單獨處理,還有一些沒有廁所信息。
library(tidyr)
library(stringr)
DATA=separate(data=DATA,col=Type,into=c("Bedrooms","Halls"),sep="室")
DATA=separate(data=DATA,col=Halls,into=c("Halls","Toilet"),sep="廳")
##將衛(wèi)生間后面的漢字去掉
DATA$Toilet<-str_replace(DATA$Toilet,"衛(wèi)","")
###如圖六,將Halls中帶有漢字去掉,因為有一些房屋信息沒有客廳,如:1室1廳,在分成臥室和客廳時,會將衛(wèi)生間分到客廳一列。
DATA$Halls<-str_replace(DATA$Halls,"衛(wèi)","")
##取出沒有客廳信息的數(shù)據(jù),這些數(shù)據(jù)被separate到Halls列
newdata<-DATA[which(DATA$Toilet%in%NA),2]
newdata
##將沒有客廳的房屋信息Halls列填充為0
DATA[which(DATA$Toilet%in%NA),2]<-0
DATA[which(DATA$Toilet%in%NA),3]<-newdata
colSums(DATA=="")
BedroomsHallsToiletAreaTowardsFloorDecorate
0020000
TotalPricePrice
00
##發(fā)現(xiàn)有2個廁所沒有信息,將其填寫為0。
DATA$Toilet[DATA$Toilet==""]<-0
##這里將Area后的㎡去掉
DATA$Area<-str_replace(DATA$Area,"㎡","")
##查看Towards的類型
table(DATA$Towards)
Towards北向東北向東南向東西向東向南北向南向西北向
512523506532190167838
西南向西向
2826
##將Floor信息帶括號的全部去除
DATA$Floor<-str_replace(DATA$Floor,"[(].*[)]","")##正則表達式
#查看Floor的類別信息
低層地下高層共1層共2層共3層共4層共5層中層
632327903661101681301016
#分別將TotalPrice和Price后面的萬元、元/㎡去掉
DATA$TotalPrice<-str_replace(DATA$TotalPrice,"萬元","")
DATA$Price<-str_replace(DATA$Price,"元/㎡","")
head(DATA)
##將數(shù)據(jù)轉換格式
DATA$Bedrooms<-as.factor(DATA$Bedrooms)
DATA$Halls<-as.factor(DATA$Halls)
DATA$Toilet<-as.factor(DATA$Toilet)
DATA$Area<-as.numeric(DATA$Area)
DATA$TotalPrice<-as.numeric(DATA$TotalPrice)
DATA$Price<-as.numeric(DATA$Price)
DATA$Towards<-as.factor(DATA$Towards)
DATA$Decorate<-as.factor(DATA$Decorate)
str(DATA)
以上數(shù)據(jù)清洗完畢。
描述性分析
這部分的主要思路是探究單個自變量對因變量的影響,對房價的影響因素進行模擬探究之前,首先對各變量進行描述性分析,以初步判斷房價的影響因素。這里探究各個因素對總價影響。
探究Bedrooms與TotalPrice的關系
table(DATA$Bedrooms)
12345679
54112257791931022051
##由于擁有6、7、9個臥室數(shù)的數(shù)量較少,這里我們排出這些數(shù)據(jù)。
DATA<-DATA[-(which(DATA$Bedrooms%in%"6")),]
12345
5411225779193102
library(ggplot2)
ggplot(DATA,aes(x=Bedrooms,y=TotalPrice))+geom_boxplot(col="red")
DATA$Bedrooms<-as.numeric(DATA$Bedrooms)
##這里將臥室數(shù)為1、2、3命名為A,4為B,5為C
DATA$Bedrooms[DATA$Bedrooms=='1']<-"A"
DATA$Bedrooms[DATA$Bedrooms=='2']<-"A"
DATA$Bedrooms[DATA$Bedrooms=='3']<-"A"
DATA$Bedrooms[DATA$Bedrooms=='4']<-"B"
DATA$Bedrooms[DATA$Bedrooms=='5']<-"C"
不同臥室數(shù),TotalPrice不同。且隨著臥室數(shù)的增多,總價越高,符合大眾的認知。
探究Halls與TotalPrice的關系
table(DATA$Halls)
0123459
2016741050771810
##5個客廳只有一個個體,我們這里將其排出
DATA<-DATA[-(which(DATA$Halls%in%"5")),]
table(DATA$Halls)
ggplot(DATA,aes(x=Halls,y=TotalPrice))+geom_boxplot(col="red")
客廳數(shù)為3時候總價最高,客廳數(shù)為0、1和2的時候總價低于客廳數(shù)3和客廳數(shù)4。
探究Toilet與TotalPrice的關系
#探究衛(wèi)生間與總價的關系
table(DATA$Toilet)
012345679
221424701167426720
#這里將衛(wèi)生間數(shù)為0、6和7的去掉
DATA<-DATA[-(which(DATA$Toilet%in%"0")),]
021424701167426000
ggplot(DATA,aes(x=Toilet,y=TotalPrice))+geom_boxplot(col="red")
一般臥室數(shù)越多,衛(wèi)生間數(shù)也越多,即衛(wèi)生間數(shù)越多,總價越高。
探究Area與TotalPrice的關系
ggplot(DATA,aes(x=Area,y=TotalPrice))+geom_point(col='red')
這個完全符合住房面積越大,總價越高。
探究Towards與TotalPrice的關系
ggplot(DATA,aes(x=Towards,y=TotalPrice))+geom_boxplot(col="red")
探究Floor與TotalPrice的關系
ggplot(DATA,aes(x=Floor,y=TotalPrice))+geom_boxplot(col="red")
圖中信息顯示樓層一共只有1、2、3、地下的總價較高。
探究Decorate與TotalPrice的關系
ggplot(DATA,aes(x=Decorate,y=TotalPrice))+geom_boxplot(col="red")
不同裝修信息對總價影響較小。
模型建立
fit<-lm(TotalPrice~Bedrooms+Halls+Toilet+Area+Towards+Floor+Decorate,data=DATA)
summary(fit)
Call:
lm(formula=TotalPrice~Bedrooms+Halls+Toilet+Area+
Towards+Floor+Decorate,data=DATA)
Residuals:
Min1QMedian3QMax
-1330.80-103.49-21.4163.882961.59
Coefficients:
EstimateStd.ErrortvaluePr(>|t|)
(Intercept)-112.763388.3010-1.2770.201697
Bedrooms2-43.593416.2533-2.6820.007359**
Bedrooms3-82.656520.7641-3.9817.04e-05***
Bedrooms4-63.309634.9521-1.8110.070198.
Bedrooms579.061854.07631.4620.143842
Halls1-5.066364.2764-0.0790.937182
Halls2-53.890565.4427-0.8230.410307
Halls3-303.975079.2280-3.8370.000127***
Halls4-528.5427104.0849-5.0784.07e-07***
Toilet2112.956619.11715.9093.87e-09***
Toilet3543.730438.805614.012<2e-16***
Toilet4735.189455.097713.343<2e-16***
Toilet5338.790684.28514.0205.98e-05***
Area5.10910.161931.557<2e-16***
Towards東北向138.908879.38171.7500.080248.
Towards東南向187.189568.53882.7310.006351**
Towards東西向176.305565.83842.6780.007453**
Towards東向210.943573.27442.8790.004022**
Towards南北向75.783157.11991.3270.184704
Towards南向60.194956.96781.0570.290763
Towards西北向75.432671.14151.0600.289091
Towards西南向169.810675.96262.2350.025467*
Towards西向234.081676.55853.0580.002253**
Floor地下-812.357863.3277-12.828<2e-16***
Floor高層12.352514.24660.8670.385991
Floor共1層-313.727852.1342-6.0182.00e-09***
Floor共2層-453.369241.6829-10.877<2e-16***
Floor共3層-601.703244.3336-13.572<2e-16***
Floor共4層-183.786636.3396-5.0574.52e-07***
Floor共5層-41.418425.7922-1.6060.108419
Floor中層-1.722313.5961-0.1270.899204
Decorate簡單裝修-63.159122.0584-2.8630.004224**
Decorate精裝修-49.327619.8544-2.4840.013033*
Decorate毛坯-157.029924.3012-6.4621.22e-10***
---
Signif.codes:0‘***’0.001‘**’0.01‘*’0.05‘.’0.1‘’1
Residualstandarderror:265.5on2794degreesoffreedom
MultipleR-squared:0.6852,AdjustedR-squared:0.6815
F-statistic:184.3on33and2794DF,p-value:<2.2e-16
模型的F檢驗拒絕原假設,說明建立的模型是顯著的;Ajusted R-squared為0.6815,模型的擬合程度尚可接受。
數(shù)據(jù)分析咨詢請掃描二維碼
若不方便掃碼,搜微信號:CDAshujufenxi
SQL Server 中 CONVERT 函數(shù)的日期轉換:從基礎用法到實戰(zhàn)優(yōu)化 在 SQL Server 的數(shù)據(jù)處理中,日期格式轉換是高頻需求 —— 無論 ...
2025-09-18MySQL 大表拆分與關聯(lián)查詢效率:打破 “拆分必慢” 的認知誤區(qū) 在 MySQL 數(shù)據(jù)庫管理中,“大表” 始終是性能優(yōu)化繞不開的話題。 ...
2025-09-18CDA 數(shù)據(jù)分析師:表結構數(shù)據(jù) “獲取 - 加工 - 使用” 全流程的賦能者 表結構數(shù)據(jù)(如數(shù)據(jù)庫表、Excel 表、CSV 文件)是企業(yè)數(shù)字 ...
2025-09-18DSGE 模型中的 Et:理性預期算子的內(nèi)涵、作用與應用解析 動態(tài)隨機一般均衡(Dynamic Stochastic General Equilibrium, DSGE)模 ...
2025-09-17Python 提取 TIF 中地名的完整指南 一、先明確:TIF 中的地名有哪兩種存在形式? 在開始提取前,需先判斷 TIF 文件的類型 —— ...
2025-09-17CDA 數(shù)據(jù)分析師:解鎖表結構數(shù)據(jù)特征價值的專業(yè)核心 表結構數(shù)據(jù)(以 “行 - 列” 規(guī)范存儲的結構化數(shù)據(jù),如數(shù)據(jù)庫表、Excel 表、 ...
2025-09-17Excel 導入數(shù)據(jù)含缺失值?詳解 dropna 函數(shù)的功能與實戰(zhàn)應用 在用 Python(如 pandas 庫)處理 Excel 數(shù)據(jù)時,“缺失值” 是高頻 ...
2025-09-16深入解析卡方檢驗與 t 檢驗:差異、適用場景與實踐應用 在數(shù)據(jù)分析與統(tǒng)計學領域,假設檢驗是驗證研究假設、判斷數(shù)據(jù)差異是否 “ ...
2025-09-16CDA 數(shù)據(jù)分析師:掌控表格結構數(shù)據(jù)全功能周期的專業(yè)操盤手 表格結構數(shù)據(jù)(以 “行 - 列” 存儲的結構化數(shù)據(jù),如 Excel 表、數(shù)據(jù) ...
2025-09-16MySQL 執(zhí)行計劃中 rows 數(shù)量的準確性解析:原理、影響因素與優(yōu)化 在 MySQL SQL 調(diào)優(yōu)中,EXPLAIN執(zhí)行計劃是核心工具,而其中的row ...
2025-09-15解析 Python 中 Response 對象的 text 與 content:區(qū)別、場景與實踐指南 在 Python 進行 HTTP 網(wǎng)絡請求開發(fā)時(如使用requests ...
2025-09-15CDA 數(shù)據(jù)分析師:激活表格結構數(shù)據(jù)價值的核心操盤手 表格結構數(shù)據(jù)(如 Excel 表格、數(shù)據(jù)庫表)是企業(yè)最基礎、最核心的數(shù)據(jù)形態(tài) ...
2025-09-15Python HTTP 請求工具對比:urllib.request 與 requests 的核心差異與選擇指南 在 Python 處理 HTTP 請求(如接口調(diào)用、數(shù)據(jù)爬取 ...
2025-09-12解決 pd.read_csv 讀取長浮點數(shù)據(jù)的科學計數(shù)法問題 為幫助 Python 數(shù)據(jù)從業(yè)者解決pd.read_csv讀取長浮點數(shù)據(jù)時的科學計數(shù)法問題 ...
2025-09-12CDA 數(shù)據(jù)分析師:業(yè)務數(shù)據(jù)分析步驟的落地者與價值優(yōu)化者 業(yè)務數(shù)據(jù)分析是企業(yè)解決日常運營問題、提升執(zhí)行效率的核心手段,其價值 ...
2025-09-12用 SQL 驗證業(yè)務邏輯:從規(guī)則拆解到數(shù)據(jù)把關的實戰(zhàn)指南 在業(yè)務系統(tǒng)落地過程中,“業(yè)務邏輯” 是連接 “需求設計” 與 “用戶體驗 ...
2025-09-11塔吉特百貨孕婦營銷案例:數(shù)據(jù)驅動下的精準零售革命與啟示 在零售行業(yè) “流量紅利見頂” 的當下,精準營銷成為企業(yè)突圍的核心方 ...
2025-09-11CDA 數(shù)據(jù)分析師與戰(zhàn)略 / 業(yè)務數(shù)據(jù)分析:概念辨析與協(xié)同價值 在數(shù)據(jù)驅動決策的體系中,“戰(zhàn)略數(shù)據(jù)分析”“業(yè)務數(shù)據(jù)分析” 是企業(yè) ...
2025-09-11Excel 數(shù)據(jù)聚類分析:從操作實踐到業(yè)務價值挖掘 在數(shù)據(jù)分析場景中,聚類分析作為 “無監(jiān)督分組” 的核心工具,能從雜亂數(shù)據(jù)中挖 ...
2025-09-10統(tǒng)計模型的核心目的:從數(shù)據(jù)解讀到?jīng)Q策支撐的價值導向 統(tǒng)計模型作為數(shù)據(jù)分析的核心工具,并非簡單的 “公式堆砌”,而是圍繞特定 ...
2025-09-10