熱線電話:13121318867

登錄
首頁精彩閱讀Python 爬取北京二手房數據,分析北漂族買得起房嗎? | 附完整源碼
Python 爬取北京二手房數據,分析北漂族買得起房嗎? | 附完整源碼
2018-08-22
收藏

Python 爬取北京二手房數據,分析北漂族買得起房嗎? | 附完整源碼

房價高是北漂們一直關心的話題,本文就對北京的二手房數據進行了分析。

本文主要分為兩部分:Python爬取趕集網北京二手房數據,R對爬取的二手房房價做線性回歸分析,適合剛剛接觸Python&R的同學們學習參考。

Python爬取趕集網北京二手房數據

入門爬蟲一個月,所以對每一個網站都使用了Xpath、Beautiful Soup、正則三種方法分別爬取,用于練習鞏固。數據來源如下:

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頁數據,在數據范圍內,大家可以自設置爬取的量
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的子節點以列表的方式輸出
'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)#設置爬取頻率,一開始我就是爬取的太猛,導致網頁需要驗證。
if__name__=='__main__':

正則爬?。何已芯苛撕镁?,還是沒有解決。

這一過程中容易遇見的問題有:

有一些房屋缺少部分信息,如缺少裝修信息,這個時候需要加一個判斷,如果不加判斷,爬取就會自動終止(我在這里跌了很大的坑)。

Data.csv知識點存儲文件路徑默認是工作目錄,關于Python中如何查看工作目錄:

importos
#查看pyhton的默認工作目錄
print(os.getcwd())
#修改時工作目錄
os.chdir('e:\\workpython')

#輸出工作目錄
e:\workpython

爬蟲打印的是字典形式,每個房屋信息都是一個字典,由于Python中excel相關庫是知識盲點,所以爬蟲的時候將字典循環直接寫入了CSV。

Pycharm中打印如下:

將字典循環直接寫入CSV效果如下:

很多初學者對于Address不知如何處理,這里強調一下Beautiful Soup 中.contents的用法,親身體會,我在這里花了好多時間才找到答案。


R對爬取的二手房房價做一般線性回歸分析

下面我們用R對抓取的趕集網北京二手房數據做一些簡單的分析。

數據的說明

Name:主要是商家的醒目標題,不具備分析參考意義

Type:臥室數、客廳數、衛生間數

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),]

#在爬取的時候加入了判斷,所以不知道爬取的數據中是否存在缺失值,這里檢查一下
colSums(is.na(DATA))

#這里將Type的臥室客廳和衛生間分為三個不同的列
##這里需要注意,有一些房屋沒有客廳如:1室1衛這時候需要單獨處理,還有一些沒有廁所信息。
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="廳")
##將衛生間后面的漢字去掉
DATA$Toilet<-str_replace(DATA$Toilet,"衛","")
###如圖六,將Halls中帶有漢字去掉,因為有一些房屋信息沒有客廳,如:1室1廳,在分成臥室和客廳時,會將衛生間分到客廳一列。
DATA$Halls<-str_replace(DATA$Halls,"衛","")
##取出沒有客廳信息的數據,這些數據被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
##發現有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)

##將數據轉換格式
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)

以上數據清洗完畢。


描述性分析

這部分的主要思路是探究單個自變量對因變量的影響,對房價的影響因素進行模擬探究之前,首先對各變量進行描述性分析,以初步判斷房價的影響因素。這里探究各個因素對總價影響。

探究Bedrooms與TotalPrice的關系

table(DATA$Bedrooms)
12345679
54112257791931022051
##由于擁有6、7、9個臥室數的數量較少,這里我們排出這些數據。
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)
##這里將臥室數為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"

不同臥室數,TotalPrice不同。且隨著臥室數的增多,總價越高,符合大眾的認知。

探究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")

客廳數為3時候總價最高,客廳數為0、1和2的時候總價低于客廳數3和客廳數4。

探究Toilet與TotalPrice的關系

#探究衛生間與總價的關系
table(DATA$Toilet)
012345679
221424701167426720
#這里將衛生間數為0、6和7的去掉
DATA<-DATA[-(which(DATA$Toilet%in%"0")),]




021424701167426000
ggplot(DATA,aes(x=Toilet,y=TotalPrice))+geom_boxplot(col="red")

一般臥室數越多,衛生間數也越多,即衛生間數越多,總價越高。

探究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,模型的擬合程度尚可接受。


數據分析咨詢請掃描二維碼

若不方便掃碼,搜微信號:CDAshujufenxi

數據分析師資訊
更多

OK
客服在線
立即咨詢
日韩人妻系列无码专区视频,先锋高清无码,无码免费视欧非,国精产品一区一区三区无码
客服在線
立即咨詢