使用python抓取并分析數據—鏈家網(requests+BeautifulSoup)
本篇文章是使用python抓取數據的第一篇,使用request+BeautifulSoup的方法對頁面進行抓取和數據提取。通過使用requests庫對鏈家網二手房列表頁進行抓取,通過BeautifulSoup對頁面進行解析,并從中獲取房源價格,面積,戶型和關注度的數據。
準備工作
首先是開始抓取前準備工作,導入需要使用的庫文件,這里主要使用的是requests和BeautifulSoup兩個。Time庫負責設置每次抓取的休息時間。這里并非全部,后續還會在過程中導入新的庫。
import requests
import time
from bs4 import BeautifulSoup
抓取列表頁
開始抓取前先觀察下目標頁面或網站的結構,其中比較重要的是URL的結構。鏈家網的二手房列表頁面共有100個,URL結構為http://bj.lianjia.com/ershoufang/pg9/,其中bj表示城市,/ershoufang/是頻道名稱,pg9是頁面碼。我們要抓取的是北京的二手房頻道,所以前面的部分不會變,屬于固定部分,后面的頁面碼需要在1-100間變化,屬于可變部分。將URL分為兩部分,前面的固定部分賦值給url,后面的可變部分使用for循環。
#設置列表頁URL的固定部分
url='http://bj.lianjia.com/ershoufang/'
#設置頁面頁的可變部分
page=('pg')
此外,還需要在很http請求中設置一個頭部信息,否則很容易被封。頭部信息網上有很多現成的,也可以使用httpwatch等工具來查看。具體細節按照具體情況進行調整。
#設置請求頭部信息
headers = {'User-Agent':'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11',
'Accept':'text/html;q=0.9,*/*;q=0.8',
'Accept-Charset':'ISO-8859-1,utf-8;q=0.7,*;q=0.3',
'Accept-Encoding':'gzip',
'Connection':'close',
'Referer':'http://www.baidu.com/link?url=_andhfsjjjKRgEWkj7i9cFmYYGsisrnm2A-TN3XZDQXxvGsM9k9ZZSnikW2Yds4s&wd=&eqid=c3435a7d00006bd600000003582bfd1f'
}
使用for循環生成1-100的數字,轉化格式后與前面的URL固定部分拼成要抓取的URL。這里我們設置每兩個頁面間隔0.5秒。抓取到的頁面保存在html中。
#循環抓取列表頁信息
for i in range(1,100):
if i == 1:
i=str(i)
a=(url+page+i+'/')
r=requests.get(url=a,headers=headers)
html=r.content
else:
i=str(i)
a=(url+page+i+'/')
r=requests.get(url=a,headers=headers)
html2=r.content
html = html + html2
#每次間隔0.5秒
time.sleep(0.5)
解析頁面并提取信息
頁面抓取完成后無法直接閱讀和進行數據提取,還需要進行頁面解析。我們使用BeautifulSoup對頁面進行解析。變成我們在瀏覽器查看源代碼中看到的樣子。
#解析抓取的頁面內容
lj=BeautifulSoup(html,'html.parser')
完成頁面解析后就可以對頁面中的關鍵信息進行提取了。下面我們分別對房源的總價,房源信息和關注度三部分進行提取。
把頁面div標簽中class=priceInfo的部分提取出來,并使用for循環將其中每個房源的總價數據存在tp中。
#提取房源總價
price=lj.find_all('div',attrs={'class':'priceInfo'})
tp=[]
for a in price:
totalPrice=a.span.string
tp.append(totalPrice)
提取房源信息和關注度的方法與提取房源價格的方法類似,下面是具體的代碼,房源信息存儲在hi中,關注度存儲在fi中。
#提取房源信息
houseInfo=lj.find_all('div',attrs={'class':'houseInfo'})
hi=[]
for b in houseInfo:
house=b.get_text()
hi.append(house)
#提取房源關注度
followInfo=lj.find_all('div',attrs={'class':'followInfo'})
fi=[]
for c in followInfo:
follow=c.get_text()
fi.append(follow)
創建數據表并清洗數據
導入pandas庫將前面提取的房源總價,和關注度等信息進行匯總生成數據表。便于后面的分析。
#導入pandas庫
import pandas as pd
#創建數據表
house=pd.DataFrame({'totalprice':tp,'houseinfo':hi,'followinfo':fi})
#查看數據表的內容
house.head()
前面提取的都只是信息,還不能直接使用,在分析前要對這些信息進行數據提取和清洗等工作。如房源信息,在表中每個房源的小區名稱,戶型,面積,朝向等信息都在一個字段中,無法直接使用。需要先進行分列操作。這里的規則比較明顯,每個信息間都是以豎線分割的,因此我們只需要以豎線進行分列即可。
#對房源信息進行分列
houseinfo_split = pd.DataFrame((x.split('|') for x in house.houseinfo),index=house.index,columns=['xiaoqu','huxing','mianji','chaoxiang','zhuangxiu','dianti'])
這是完成分列后的新數據表,房源的各種信息以及成為單獨的字段。
#查看分列結果
houseinfo_split.head()
將分列后的新數據表在重新拼接回原有的數據表中,這樣在后面的分析過程中可以與其他字段的信息配合使用。
#將分列結果拼接回原數據表
house=pd.merge(house,houseinfo_split,right_index=True, left_index=True)
完成拼接后的數據表中既包含了原有字段,也包含了分列后的新增字段。
#查看拼接后的數據表
house.head()
使用相同的方法對房源關注度字段進行分列和拼接操作。這里的分列規則是斜杠。
#對房源關注度進行分列
followinfo_split = pd.DataFrame((x.split('/') for x in house.followinfo),index=house.index,columns=['guanzhu','daikan','fabu'])
#將分列后的關注度信息拼接回原數據表
house=pd.merge(house,followinfo_split,right_index=True, left_index=True)
房源戶型分布情況
前面我們經過對房源信息的分列獲取了房源的朝向,戶型等信息,這里我們對房源的戶型情況進行匯總,看看北京在售二手房的戶型分布情況。
首先按房源的戶型對房源數量進行匯總,下面是具體的代碼和結果。
#按房源戶型類別進行匯總
huxing=house.groupby('huxing')['huxing'].agg(len)
#查看戶型匯總結果
huxing
導入數值計算庫mumpy對數據進行處理,并使用matplotlib繪制房源戶型分布條形圖。
#導入圖表庫
import matplotlib.pyplot as plt
#導入數值計算庫
import numpy as np
#繪制房源戶型分布條形圖
plt.rc('font', family='STXihei', size=11)
a=np.array([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20])
plt.barh([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20],huxing,color='#052B6C',alpha=0.8,align='center',edgecolor='white')
plt.ylabel('戶型')
plt.xlabel('數量')
plt.xlim(0,1300)
plt.ylim(0,20)
plt.title('房源戶型分布情況')
plt.legend(['數量'], loc='upper right')
plt.grid(color='#95a5a6',linestyle='--', linewidth=1,axis='y',alpha=0.4)
plt.yticks(a,('1室0廳','1室1廳','1室2廳','2室0廳','2室1廳','2室2廳','3室0廳','3室1廳','3室2廳','3室3廳','4室1廳','4室2廳','4室3廳','5室2廳','5室3廳','6室1廳','6室2廳','7室2廳','7室3廳'))
plt.show()
北京在售二手房中戶型從1室0廳到7室3廳近20種分布廣泛。在所有的戶型中數量最多的是2室1廳,其次為3室1廳和3室2廳,以及2室2廳。較小的1室1廳數量也較多。較大的戶型數量較少。另外,從在售戶型的分布中我們也可以推測出售房人的一些情況。
房源面積分布情況
在數據表中,房源面積通過分列以及單獨提取出來,但數字與中文的格式并不能直接使用。我們還需要對房源面積字段進行二次分列處理,提取出面積的數值。方法與前面的分列方法類似,我們使用“平”作為分列規則對房源面積進行二次分列。并將分列后的結果拼接回原數據表中。
#對房源面積進行二次分列
mianji_num_split = pd.DataFrame((x.split('平') for x in house.mianji),index=house.index,columns=['mianji_num','mi'])
#將分列后的房源面積拼接回原數據表
house=pd.merge(house,mianji_num_split,right_index=True, left_index=True)
分列后的數據在使用前還需要進行清洗,通常的操作包括去除空格和格式轉換。下面我們先對房源面積的值去除兩端的空格,然后更改數值的格式以方便后面的計算。
#去除mianji_num字段兩端的空格
house['mianji_num']=house['mianji_num'].map(str.strip)
#更改mianji_num字段格式為float
house['mianji_num']=house['mianji_num'].astype(float)
清洗后的房源面積字段可以開始分析了。首先查看所有北京在售二手房的面積范圍,下面是代碼和結果。房源面積從18.85到332.63。
#查看所有房源面積的范圍值
house['mianji_num'].min(),house['mianji_num'].max()
(18.850000000000001, 332.63)
有了房源面積的范圍后,就可以對面積進行分組了,我們以50為區間將房源面積分為7組。并統計所有房源在這7組中的分布情況。
#對房源面積進行分組
bins = [0, 50, 100, 150, 200, 250, 300, 350]
group_mianji = ['小于50', '50-100', '100-150', '150-200','200-250','250-300','300-350']
house['group_mianji'] = pd.cut(house['mianji_num'], bins, labels=group_mianji)
#按房源面積分組對房源數量進行匯總
group_mianji=house.groupby('group_mianji')['group_mianji'].agg(len)
使用房源面積分組字段對房源數量進行分組并繪制條形圖。
#繪制房源面積分布圖
plt.rc('font', family='STXihei', size=15)
a=np.array([1,2,3,4,5,6,7])
plt.barh([1,2,3,4,5,6,7],group_mianji,color='#052B6C',alpha=0.8,align='center',edgecolor='white')
plt.ylabel('面積分組')
plt.xlabel('數量')
plt.title('房源面積分布')
plt.legend(['數量'], loc='upper right')
plt.grid(color='#95a5a6',linestyle='--', linewidth=1,axis='y',alpha=0.4)
plt.yticks(a,('小于50', '50-100', '100-150', '150-200','200-250','250-300','300-350'))
plt.show()
在所有房源中,數量最多的是50-100,其次為100-150。隨著面積增加數量減少。小于50的小面積房源也有一定數量的房源。
房源關注度分布情況
房源關注度的情況與房源面積類似,第一次分列處理后得到的數據包含數字和中文,無法直接使用,需要再次通過分列處理提取關注度的數值,并對數值進行清洗和格式轉換。下面是具體的代碼。
#對房源關注度進行二次分列
guanzhu_num_split = pd.DataFrame((x.split('人') for x in house.guanzhu),index=house.index,columns=['guanzhu_num','ren'])
#將分列后的關注度數據拼接回原數據表
house=pd.merge(house,guanzhu_num_split,right_index=True, left_index=True)
#去除房源關注度字段兩端的空格
house['guanzhu_num']=house['guanzhu_num'].map(str.strip)
#更改房源關注度及總價字段的格式
house[['guanzhu_num','totalprice']]=house[['guanzhu_num','totalprice']].astype(float)
清洗完后查看所有房源關注度的區間,關注度從0到725。也就是說有些房子很熱門,而有些房子沒有人關注。這可能和房源上線和更新的情況有關,此外還要考慮房源的銷售速度,熱門房源可能很搶手,剛上線就成交了。因此我們對情況進行簡化,暫時忽略掉這些復雜的情況。僅對關注度的分布情況進行統計。
#查看房源關注度的區間
house['guanzhu_num'].min(),house['guanzhu_num'].max()
(0.0, 725.0)
將關注度以100為區間分為8組,并按關注度區間進行匯總統計房源數量。查看在售房源的關注度分布情況。
#對房源關注度進行分組
bins = [0, 100, 200, 300, 400, 500, 600, 700,800]
group_guanzhu = ['小于100', '100-200', '200-300', '300-400','400-500','500-600','600-700','700-800']
house['group_guanzhu'] = pd.cut(house['guanzhu_num'], bins, labels=group_guanzhu)
group_guanzhu=house.groupby('group_guanzhu')['group_guanzhu'].agg(len)
繪制房源關注度分布條形圖。
#繪制房源關注度分布圖
plt.rc('font', family='STXihei', size=15)
a=np.array([1,2,3,4,5,6,7,8])
plt.barh([1,2,3,4,5,6,7,8],group_guanzhu,color='#052B6C',alpha=0.8,align='center',edgecolor='white')
plt.ylabel('關注度分組')
plt.xlabel('數量')
plt.xlim(0,3000)
plt.title('房源關注度分布')
plt.legend(['數量'], loc='upper right')
plt.grid(color='#95a5a6',linestyle='--', linewidth=1,axis='y',alpha=0.4)
plt.yticks(a,('小于100', '100-200', '200-300', '300-400','400-500','500-600','600-700','700-800'))
plt.show()
在3000個房源中,近2500個房源的關注度小于100,關注度大于400的房源則較少。這里需要再次說明的是關注度數據無法準確的表示房源的熱門程度。熱門房源可能由于出售速度快而關注度較少。因此關注度數據僅供參考。
房源聚類分析
最后,我們對所有在售房源按總價,面積和關注度進行聚類分析。將在售房源按總價,面積和關注度的相似性分在不同的類別中。
#導入sklearn中的KMeans進行聚類分析
from sklearn.cluster import KMeans
#使用房源總價,面積和關注度三個字段進行聚類
house_type = np.array(house[['totalprice','mianji_num','guanzhu_num']])
#設置質心數量為3
clf=KMeans(n_clusters=3)
#計算聚類結果
clf=clf.fit(house_type)
通過計算我們將在售房源分為三個類別,下面是每個類別的中心點坐標。
#查看分類結果的中心坐標
clf.cluster_centers_
array([[ 772.97477064, 112.02389908, 58.96330275],
[ 434.51073861, 84.92950236, 61.20115244],
[ 1473.26719577, 170.65402116, 43.32275132]])
#在原數據表中標注所屬類別
house['label']= clf.labels_
根據三個類別在總價,面積和關注度三個點的中心坐標,我們將在售房源分為三個類別,第一個類別是總價低,面積低,關注度高的房源。第二個類別是總價居中,面積居中,關注度居中的類別。第三個類別是總價高,面積高,關注度低的類別。
從營銷和用戶體驗的角度來看,在廣告和列表頁的默認排序中應該給予總價400萬,面積80屬性的房源更高的權重。這個類別的房源可以吸引最多的用戶關注。
—【所有文章及圖片版權歸 藍鯨(王彥平)所有。歡迎轉載,但請注明轉自“藍鯨網站分析博客”。】—
來自:http://bluewhale.cc/2016-12-04/use-python-crawl-and-analysis-data-lianjia-requests-and-beautifulsoup.html