1. 程式人生 > >學習python抓取資料——鏈家北京二手房資料

學習python抓取資料——鏈家北京二手房資料

最近在學習用Python進行資料分析、機器學習,基本都是用現成資料集進行模型訓練及驗證,想用一些實際資料看一下效果,於是想到用Python嘗試抓取一些實際資料。
目標:爬取鏈家網北京二手房房價、位置、面積等資料
環境:Python3.5.2,Anaconda4.2.0
在這裡插入圖片描述

1.準備工作

首先,匯入所需要的庫,主要有urllib.request、BeautifulSoup、Pandas、Numpy、re。

from urllib.request import urlopen
from bs4 import BeautifulSoup
import pandas as pd
import
numpy as np import re

2.抓取資料

首先,瞭解一下目標網站的URL結構,例如 https://bj.lianjia.com/ershoufang/dongcheng/pg2/

  • bj表示城市,北京
  • ershoufang是頻道名稱,二手房
  • dongcheng是城區名稱,東城區
  • pg2是頁面碼,第二頁
    在這裡插入圖片描述

例如,我們要抓取北京各個區二手房頻道,所以前面城市、頻道名稱不會變,屬於固定部分;後面的城區要遍歷北京各個區(東城、西城、朝陽…),頁碼需要在1-所選城區總頁數間變化,屬於可變部分。將URL分為兩部分,前面的固定部分賦值給url,後面的可變部分用雙層for迴圈遍歷,外層迴圈遍歷城區,內層迴圈遍歷所選城區的頁面。其中,需要獲取所選城區包含的總頁數,提取div標籤中class=page-box fr的第一個子標籤屬性page-data的值。
在這裡插入圖片描述

chengqu={'dongcheng':'東城區','xicheng':'西城區','chaoyang':'朝陽區','haidian':'海淀區','fengtai':'豐臺區','shijingshan':'石景山區', 'tongzhou':'通州區','changping':'昌平區','daxing':'大興區','shunyi':'順義區','fangshan':'房山區'}
for cq in chengqu.keys():
    url='https://bj.lianjia.com/ershoufang/'+cq+'/'   #組成所選城區的URL
    html=urlopen(url)
    bsObj=BeautifulSoup(html)  #解析抓取的頁面內容
    total_page=re.sub('\D','',bsObj.find('div','page-box fr').contents[0].attrs['page-data'])[:-1]  #獲取所選城區總頁數
    print ('total_page',total_page)
    for j in np.arange(1,int(total_page)+1):
        page_url=url+'pg'+str(j)  #組成所選城區頁面的URL

然後,使用BeautifulSoup對頁面進行解析。

 page_html=urlopen(page_url)
 page_bsObj=BeautifulSoup(page_html)

接著,提取頁面中的關鍵資訊進行提取,主要對房屋資訊、房屋位置、總價和單價進行提取。

依次把頁面div標籤中class為houseInfo、positionInfo、totalPrice、unitPrice的部分提取出來,用get_text()獲取對應標籤中的資訊,其中houseInfo、positionInfo包含房屋的多種屬性,用split()對其進行分列,只選取了houseInfo包含6個屬性且positionInfo包含3個屬性的資料。另外,對於單價用get_text()後得到“單價100748元/平米”,包含了文字和數字,用re.sub()正則匹配出數字部分。最後,依次把提取到的資訊新增到對應列表中。

info=bsObj.findAll("div",{"class":"houseInfo"})
position_info=bsObj.findAll("div",{"class":"positionInfo"})
totalprice=bsObj.findAll("div",{"class":"totalPrice"})
unitprice=bsObj.findAll("div",{"class":"unitPrice"})

 house_loc=[]  #房屋所在小區
 house_type=[] #房屋戶型
 house_area=[] #房屋面積
 house_direction=[] #房屋朝向
 house_decorating=[] #房屋裝修
 house_lift=[] #有無電梯
 house_floor=[] #房屋樓層
 house_year=[] #建造年份
 house_position=[] #房屋位置
 t_price=[] #房屋總價
 u_price=[] #房屋單價

 for i_info,i_pinfo,i_tp,i_up in zip(info,position_info,totalprice,unitprice):
     if len(i_info.get_text().split('/'))==6 and len(i_pinfo.get_text().split('/'))==3:
         #分列houseinfo並依次獲取房屋所在小區、戶型、面積、朝向、裝修、有無電梯各欄位
         house_loc.append(i_info.get_text().split('/')[0])
         house_type.append(i_info.get_text().split('/')[1])
         house_area.append(i_info.get_text().split('/')[2][:-2])
         house_direction.append(i_info.get_text().split('/')[3].replace(' ',''))
         house_decorating.append(i_info.get_text().split('/')[4])
         house_lift.append(i_info.get_text().split('/')[5])
         #分列positioninfo並依次獲房屋樓層、建造年份、位置各欄位
         house_floor.append(i_pinfo.get_text().split('/')[0])
         house_year.append(i_pinfo.get_text().split('/')[1][:5])
         house_position.append(i_pinfo.get_text().split('/')[2])
         #獲取房屋總價和單價
         t_price.append(i_tp.span.string)
         u_price.append(re.sub('\D','',i_up.get_text()))

將提取的資料匯入pandas之中生成資料表。

#將資料匯入pandas之中生成資料表
 house_data=pd.DataFrame()
 house_data[u'城區']=[chengqu[cq]]*len(house_loc)
 house_data[u'小區名稱']=house_loc
 house_data[u'房型']=house_type
 house_data[u'面積']=house_area
 house_data[u'朝向']=house_direction
 house_data[u'裝修']=house_decorating
 house_data[u'有無電梯']=house_lift
 house_data[u'樓層']=house_floor
 house_data[u'建造年份']=house_year
 house_data[u'位置']=house_position
 house_data[u'總價']=t_price
 house_data[u'單價']=u_price
 print (house_data)

將資料存入到csv中,便於後續分析。

house_data.to_csv('house_bj.csv', mode='a', header=False,ecoding='gb2312',index=None)

總共提取到北京11個區28560條二手房資訊。
在這裡插入圖片描述
最後,附上完整程式碼~~

from urllib.request import urlopen
from bs4 import BeautifulSoup
import pandas as pd
import numpy as np
import re

chengqu={'dongcheng':'東城區','xicheng':'西城區','chaoyang':'朝陽區','haidian':'海淀區','fengtai':'豐臺區','shijingshan':'石景山區',
         'tongzhou':'通州區','changping':'昌平區','daxing':'大興區','shunyi':'順義區','fangshan':'房山區'}
for cq in chengqu.keys():
    url='https://bj.lianjia.com/ershoufang/'+cq+'/'   #組成所選城區的URL
    html=urlopen(url)
    bsObj=BeautifulSoup(html)
    total_page=re.sub('\D','',bsObj.find('div','page-box fr').contents[0].attrs['page-data'])[:-1]  #獲取所選城區總頁數
    print ('total_page',total_page)
    
    for j in np.arange(1,int(total_page)+1):
        page_url=url+'pg'+str(j)  #組成所選城區頁面的URL
        #print (page_url)
        page_html=urlopen(page_url)
        page_bsObj=BeautifulSoup(page_html)
        info=bsObj.findAll("div",{"class":"houseInfo"})
        position_info=bsObj.findAll("div",{"class":"positionInfo"})
        totalprice=bsObj.findAll("div",{"class":"totalPrice"})
        unitprice=bsObj.findAll("div",{"class":"unitPrice"})
                
        house_loc=[]  #房屋所在小區
        house_type=[] #房屋戶型
        house_area=[] #房屋面積
        house_direction=[] #房屋朝向
        house_decorating=[] #房屋裝修
        house_lift=[] #有無電梯
        house_floor=[] #房屋樓層
        house_year=[] #建造年份
        house_position=[] #房屋位置
        t_price=[] #房屋總價
        u_price=[] #房屋單價

        for i_info,i_pinfo,i_tp,i_up in zip(info,position_info,totalprice,unitprice):
            if len(i_info.get_text().split('/'))==6 and len(i_pinfo.get_text().split('/'))==3:
                #分列houseinfo並依次獲取房屋所在小區、戶型、面積、朝向、裝修、有無電梯各欄位
                house_loc.append(i_info.get_text().split('/')[0])
                house_type.append(i_info.get_text().split('/')[1])
                house_area.append(i_info.get_text().split('/')[2][:-2])
                house_direction.append(i_info.get_text().split('/')[3].replace(' ',''))
                house_decorating.append(i_info.get_text().split('/')[4])
                house_lift.append(i_info.get_text().split('/')[5])
                #分列positioninfo並依次獲房屋樓層、建造年份、位置各欄位
                house_floor.append(i_pinfo.get_text().split('/')[0])
                house_year.append(i_pinfo.get_text().split('/')[1][:5])
                house_position.append(i_pinfo.get_text().split('/')[2])
                #獲取房屋總價和單價
                t_price.append(i_tp.span.string)
                u_price.append(re.sub('\D','',i_up.get_text()))
        #將資料匯入pandas之中生成資料表
        house_data=pd.DataFrame()
        house_data[u'城區']=[chengqu[cq]]*len(house_loc)
        house_data[u'小區名稱']=house_loc
        house_data[u'房型']=house_type
        house_data[u'面積']=house_area
        house_data[u'朝向']=house_direction
        house_data[u'裝修']=house_decorating
        house_data[u'有無電梯']=house_lift
        house_data[u'樓層']=house_floor
        house_data[u'建造年份']=house_year
        house_data[u'位置']=house_position
        house_data[u'總價']=t_price
        house_data[u'單價']=u_price
        #print (house_data)
        #將資料存入到csv中,便於後續分析
        house_data.to_csv('house_bj.csv', mode='a', header=False,ecoding='gb2312',index=None)