步驟
-
數據所在的url
-
發送網絡請求
-
數據的解析(我們需要的數據)
-
數據的保存
下面分步進行詳細的實現
(完整代碼放在最后)
爬取的網站:https://gl.lianjia.com/zufang/
-
分析需要爬取的數據是否是靜態數據,查看網頁源碼
# URL地址
url = 'https://gl.lianjia.com/zufang/'發現我們需要爬取的數據(地區、戶型、面積等)是靜態的
-
構建一個請求頭,進行偽裝,偽裝成一個瀏覽器用戶。
因為要是不寫的話,訪問某些網站的時候會被認出來爬蟲,顯示錯誤,錯誤代碼。
# 請求頭,鍵值對形式
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36 Edg/95.0.1020.30'}獲得請求頭的方式:
在URL下按下
F12
,打開開發者工具,來到網絡(network),可以看到該頁面的所有的網絡請求,我們隨意點擊一個,找到標頭下的User-Agent
,它的內容就是我們需要的,其他的那些是瀏覽器自帶的、可以不管。
1.2、發送網絡請求
-
導入發送網絡請求的模塊,使用其來發送請求
import requests
下載該模塊的依賴,在控制台中輸入
pip install requests
-
實現發送請求,帶上請求頭。使用response接收返回值
# 發送網絡請求
response = requests.get(url=url, headers=headers)
# print(response) # 響應碼為200代表成功
# html_data = response.text # 這是網頁源碼
# print(html_data) # 可以打印到控制台看看是否和網頁源碼一致
至此,response是我們拿到的網頁的所有數據。下面就是對其進行解析,獲得我們需要的數據
1.3、數據的解析
-
導入數據解析模塊(步驟和上面一樣)
import parsel
pip install parsel
轉換數據類型
將其轉為一個對象,才可以用於解析
selector = parsel.Selector(html_data)
這里使用xpath解析,進行數據的采集
分析我們需要采集的數據(地區、小區、戶型、面積、價格、朝向、出租方式等)
使用以下方法需要對html 、css有一定的了解。也可以直接搬過去使用
# 將其轉為一個對象
selector = parsel.Selector(html_data)
lis = selector.xpath('//div[@class="content__list"]/div') # 定位到每一條信息的標簽
for li in lis:
detail_hire = li.xpath('.//div/p/a/text()').get() # 出租方式
detail_hire = detail_hire.strip()[0:2] # 去除前后空格,截取出租方式
detail_url = 'https://gl.lianjia.com' + li.xpath('.//a/@href').get() # 租房詳情地址,需要拼接
detail_area = li.xpath('.//div/p[2]/text()[5]').get().strip() # 出租面積
detail_direction = li.xpath('.//div/p[2]/text()[6]').get().strip() # 朝向
detail_type = li.xpath('.//div/p[2]/text()[7]').get().strip() # 戶型
detail_region = li.xpath('.//div/p[2]/a[2]/text()').get() # 地區
detail_village = li.xpath('.//div/p[2]/a[3]/text()').get() # 小區
detail_rent = li.xpath('.//div/span/em/text()').get() # 租金
# 運行,看是否能打印出結果
print(detail_hire, detail_region, detail_village, detail_area,
detail_direction, detail_type, detail_rent, detail_url, sep=' | ')
1.4、數據的保存
# 數據的保存,第一個參數:保存的文件名 ; a:追加寫,
with open('租房網(桂林)數據.csv', mode='a', encoding='UTF-8', newline='') as f:
csv_write = csv.writer(f)
csv_write.writerow([detail_hire, detail_region, detail_village, detail_area, detail_direction, detail_type, detail_rent, detail_url])
到這里,完成了一個頁面的采集,那如何完成這100 多頁的采集?
點擊翻頁,找規律,發現url是有規律的。
那么我們將頁面的規律構建出來,便可以實現循環查詢了
那我們只需要在最外層加循環,改變url的路徑即可。
因為是只有100頁,所以范圍設置為101
會出現亂碼,百度搜索如何解決csv亂碼問題
處理一下文檔,因為沒有添加標題欄,可以打開爬取好的文件手動加上。方便后面進行數據處理,你也可以嘗試使在代碼中添加
出租方式,地區,小區,出租面積,朝向,戶型,租金,租房詳情地址
完整代碼
爬取一頁數據的完整代碼
import csv
import requests
import parsel
# URL地址
url = 'https://gl.lianjia.com/zufang/pg1'
# 請求頭,鍵值對形式
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36 Edg/95.0.1020.30'}
# 發送網絡請求
response = requests.get(url=url, headers=headers)
# print(response) # 響應碼為200代表成功
html_data = response.text # 這是網頁源碼
# print(html_data) # 可以打印到控制台看看是否和網頁源碼一致
# 將其轉為一個對象
selector = parsel.Selector(html_data)
lis = selector.xpath('//div[@class="content__list"]/div') # 定位到每一條信息的標簽
for li in lis:
detail_hire = li.xpath('.//div/p/a/text()').get() # 出租方式
detail_hire = detail_hire.strip()[0:2] # 去除前后空格,截取出租方式
detail_url = 'https://gl.lianjia.com' + li.xpath('.//a/@href').get() # 租房詳情地址,需要加上前綴
detail_area = li.xpath('.//div/p[2]/text()[5]').get().strip() # 出租面積
detail_direction = li.xpath('.//div/p[2]/text()[6]').get().strip() # 朝向
detail_type = li.xpath('.//div/p[2]/text()[7]').get().strip() # 戶型
detail_region = li.xpath('.//div/p[2]/a[2]/text()').get() # 地區
detail_village = li.xpath('.//div/p[2]/a[3]/text()').get() # 小區
detail_rent = li.xpath('.//div/span/em/text()').get()# 租金
print(detail_hire, detail_region, detail_village, detail_area,
detail_direction, detail_type, detail_rent, detail_url, sep=' | ')
# 數據的保存,a追加寫
with open('租房網(桂林)數據.csv', mode='a', encoding='UTF-8', newline='') as f:
csv_write = csv.writer(f)
csv_write.writerow([detail_hire, detail_region, detail_village, detail_area, detail_direction, detail_type, detail_rent, detail_url])
爬取該站點的全部(區別只是多了一層循環)
import csv
import requests
import parsel
for page in range(1, 101):
# URL地址
print(f'\n=================正在爬取第{page}頁的數據=======================')
url = f'https://gl.lianjia.com/zufang/pg{page}'
# 請求頭,鍵值對形式
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36 Edg/95.0.1020.30'}
# 發送網絡請求
response = requests.get(url=url, headers=headers)
# print(response) # 響應碼為200代表成功
html_data = response.text # 這是網頁源碼
# print(html_data) # 可以打印到控制台看看是否和網頁源碼一致
# 將其轉為一個對象
selector = parsel.Selector(html_data)
lis = selector.xpath('//div[@class="content__list"]/div') # 定位到每一條信息的標簽
for li in lis:
detail_hire = li.xpath('.//div/p/a/text()').get() # 出租方式
detail_hire = detail_hire.strip()[0:2] # 去除前后空格,截取出租方式
detail_url = 'https://gl.lianjia.com' + li.xpath('.//a/@href').get() # 租房詳情地址,需要加上前綴
detail_area = li.xpath('.//div/p[2]/text()[5]').get().strip() # 出租面積
detail_direction = li.xpath('.//div/p[2]/text()[6]').get().strip() # 朝向
detail_type = li.xpath('.//div/p[2]/text()[7]').get().strip() # 戶型
detail_region = li.xpath('.//div/p[2]/a[2]/text()').get() # 地區
detail_village = li.xpath('.//div/p[2]/a[3]/text()').get() # 小區
detail_rent = li.xpath('.//div/span/em/text()').get() # 租金
# print(detail_hire, detail_region, detail_village, detail_area, detail_direction, detail_type, detail_rent, detail_url, sep=' | ')
# 數據的保存,a追加寫
with open('租房網(桂林)數據all.csv', mode='a', encoding='UTF-8', newline='') as f:
csv_write = csv.writer(f)
csv_write.writerow([detail_hire, detail_region, detail_village, detail_area, detail_direction, detail_type, detail_rent, detail_url])
2、數據分析及可視化
步驟
探索性數據分析流程:
-
安裝數據分析及可視化的工具
-
獲取原始數據(即爬蟲爬到的代碼,可以是excel或者數據庫)
-
數據處理
-
數據可視化
-
分析、得出結論
2.1、Jupyter Notebook工具安裝
這里使用工具Jupyter Notebook
對數據進行可視化分析
Jupyter Notebook的安裝(結合該教程:https://www.jianshu.com/p/91365f343585)
補充幾點:
我是使用pip命令安裝
在使用安裝命令的時候需要管理員權限,所以我們按下win+x
,選擇管理員的控制台
然后再執行把pip升級到最新版本
-
Python 3.x
pip3 install --upgrade pip
-
Python 2.x
pip install --upgrade pip
-
注意:老版本的pip在安裝Jupyter Notebook過程中或面臨依賴項無法同步安裝的問題。因此強烈建議先把pip升級到最新版本。
同樣的也是在這里執行Jupyter Notebook的安裝命令,加上 -i 表示使用鏡像, 后面接着鏡像地址,我這里是阿里雲的,如果不使用鏡像下載,下載會很慢。上面的命令也可以使用鏡像
pip install jupyter
pip install jupyter -i https://mirrors.aliyun.com/pypi/simple (推薦使用鏡像)
然后等執行完畢,再pycharm的控制台或者管理員控制台中輸入
jupyter notebook
就能自動打開jupyter notebook了,如圖,安裝成功
新建一個操作窗口
導入工具,在新窗口的命令行中執行,先下載依賴,在控制台中執行
pip install pandas -i https://mirrors.aliyun.com/pypi/simple
pip install pyecharts -i https://mirrors.aliyun.com/pypi/simple
import pandas as pd
from pyecharts.charts import *
到這里,完成了數據分析的前期准備
2.2、導入原始數據
df = pd.read_csv(r'D:\learningappDataSave\python\homework\com\yong\pc\租房網(桂林)數據all.csv',engine='python')
df.head() # 查看前五條
# df # 查看全部
2.3、數據處理
1、查看數據類型
df.dtypes
數據類型是因為我們在爬取的時候加上了單位,所以都是object(字符串)類型。如果不加,那有可能是其他類型,比如int
2、查看表格丟失數據
df.isnull()
對應的數據丟失為true,否則為false
但這樣並不直觀,對他進行一個求和統計,能更清楚的看到缺失情況
3、刪除重復值
df.drop_duplicates(inplace=True)
輸出結果為空,說明無重復值
2.4、數據可視化
要求:計算桂林各個地區的不同戶型的:
-
平均價格
-
最低價格
-
最高價格
並進行可視化
-
不同戶型價格前25%中不同地區的占比並進行可視化。
-
結合桂林實際情況和獲取的數據,分析不同地區租金最高的小區。
思路:
統計出桂林的地區數量
在每個地區統計出該地區的不同戶型的三種價格
1、總體分析(多做的一部分,滿足要求的在戶型分析)
統計每個區的房源數量(第一條表示七星區有555套房源)
df.groupby('地區').count()
結果分析:
臨桂區的房源數量是最多的,靈川是最少的。
而且最多地區的房源數量是最少的8倍多。
可推測地區人口分布的情況
-
統計每個地區的平均租金價格
df_means = df.groupby('地區')['租金'].mean()
df_means
可視化:
獲取x軸:df_means.index.tolist()
y軸同理
畫出x、y軸。y軸可添加多個
bar = (
Bar()
.add_xaxis(df_means.index.tolist())
.add_yaxis('平均值',df_means.values.astype('int64').tolist())
.add_yaxis('房源數量',df_counts['租金'].values.tolist())
)
bar.render_notebook()
結果分析:
秀峰區的房源數量不多,但是平均租金最高。
臨桂區的房源數量少,租金反而是最低的。
可以推測消費水平
-
最低價格、最高價格
bar = (
Bar()
.add_xaxis(df_means.index.tolist())
.add_yaxis('租金最大值',df.groupby('地區')['租金'].max().values.astype('int64').tolist())
.add_yaxis('租金最小值',df.groupby('地區')['租金'].min().values.astype('int64').tolist())
)
bar.render_notebook()
結果分析:
房源的最高價和最低價相差最大的是七星區
七星區房源的最高價是幾個區中最高的
靈川房源的最低價是幾個區中最低的
秀峰區房源的最低價是幾個區中最高的
推測秀峰區最低住房消費水平是幾個區中最高的,靈川是最低的,七星區住房消費水平都有,要高有高,要低有低。
2、戶型分析
-
計算桂林各個地區的不同戶型的平均價格、最低價格和最高價格並進行可視化
-
不同戶型價格前25%中不同地區的占比並進行可視化。
思路:
-
統計出桂林的地區數量
-
在每個地區統計出該地區的不同戶型的三種價格
統計出不同地區的不同戶型
df.groupby(['地區','戶型']).count()
因為這里有146個數據,說明x軸會有146.如果將平均值、最大值、最小值放在一張圖中會看不清楚。
將其拆開了。。。
不同地區、不同戶型的平均值
bar = (
Bar()
.add_xaxis(df.groupby(['地區','戶型']).count().index.tolist())
.add_yaxis('租金平均值',df.groupby(['地區','戶型'])['租金'].mean().values.astype('int64').tolist())
)
bar.render_notebook()
最大值
最小值
不同戶型價格前25%中不同地區的占比並進行可視化。
分析不同地區租金最高的小區
根據地區分組,求出每個地區租金最高的小區(小區可能包含多個房源)
每個地區租金最低的小區
df.groupby('地區')['小區','租金'].max()
大概知道每個區的哪一片區域的消費水平比較高
每個地區租金最低的小區
大概知道每個區的哪一片區域的消費水平比較高
2.5、分析得出結論
結果分析:
臨桂區的房源數量是最多的,靈川是最少的。
而且最多地區的房源數量是最少的8倍多。
可推測地區人口分布的情況
結果分析:
秀峰區的房源數量不多,但是平均租金最高。
臨桂區的房源數量少,租金反而是最低的。
可以推測消費水平
結果分析:
房源的最高價和最低價相差最大的是七星區
七星區房源的最高價是幾個區中最高的
靈川房源的最低價是幾個區中最低的
秀峰區房源的最低價是幾個區中最高的
推測秀峰區最低住房消費水平是幾個區中最高的,靈川是最低的,七星區住房消費水平都有,要高有高,要低有低。
可以根據小區的租房金額來推測該區域的消費水平
參考資料
數據分析及可視化:https://www.bilibili.com/video/BV1xP4y1x7wp?spm_id_from=333.999.0.0