一、選題的背景
為什么要選擇此選題?要達到的數據分析的預期目標是什么?(10 分)
通過爬取Q房二手房信息,對爬取的數據進行進一步清洗處理,分析各維度的數據,篩選對房價有顯著影響的特征變量,探索上海二手房整體情況、價格情況。
二、主題式網絡爬蟲設計方案(10 分)
1.主題式網絡爬蟲名稱:二手房爬蟲及數據分析
2.主題式網絡爬蟲爬取的內容與數據特征分析:
通過request爬取Q房二手房的信息、BeautifulSoup分析網頁結構獲取數據,其中內容為上海二手房的房屋簡介、樓層、規格、地址、房價、面積。
3.主題式網絡爬蟲設計方案概述:
需要分為幾個步驟實現:通過獲取網頁資源,使用etree解析網頁,定位爬取資源將數據保存到csv文件中。
三、主題頁面的結構特征分析(10 分)
數據來源:https://shanghai.qfang.com/
Htmls頁面解析:
通過find方法查找所需要的相關頁面代碼
四、網絡爬蟲程序設計(60 分)
數據爬取及采集:
1 #導入庫 2 import requests 3 from lxml import etree 4 import time 5 import re 6 import pandas as pd 7 8 #初始化空列表 9 jianjie_list, louceng_list, guige_list, dz_list, fangjia_list, mianji_list = [], [], [], [], [], [] 10 11 for a in range(10): 12 #爬取前10頁的內容 13 url = "https://shanghai.qfang.com/sale/f{}".format(a*10) 14 15 #設置請求頭 16 headers = { 17 "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36" 18 } 19 #requests請求鏈接 20 resp = requests.get(url,headers=headers).text 21 22 #使用lxml模塊中的etree方法將字符串轉化為html標簽 23 html = etree.HTML(resp) 24 25 #xpath定位標簽 26 list = html.xpath("/html/body/div[4]/div/div[1]/div[4]/ul/li") 27 28 #爬取內容具體鏈接 29 for li in list: 30 #爬取簡介 31 jianjie = li.xpath("./div[2]/div[1]/a/text()")[0] 32 #爬取樓層 33 louceng = li.xpath("./div[2]/div[2]/p[4]/text()")[0] 34 #爬取規格 35 guige = li.xpath("./div[2]/div[2]/p[1]/text()")[0] 36 #爬取地址 37 dz = li.xpath("./div[2]/div[3]/div/text()")[0] 38 #爬取房價 39 fangjia = li.xpath("./div[3]/p[2]/text()")[0] 40 #爬取面積 41 mianji = li.xpath("./div[2]/div[2]/p[2]/text()")[0] 42 43 #輸出 44 print(jianjie) 45 print(louceng) 46 print(guige) 47 print(dz) 48 print(fangjia) 49 print(mianji) 50 # 將字段存入初始化的列表中 51 jianjie_list.append(jianjie) 52 louceng_list.append(louceng) 53 guige_list.append(guige) 54 dz_list.append(dz) 55 fangjia_list.append(fangjia) 56 mianji_list.append(mianji) 57 58 #pandas中的模塊將數據存入 59 df = pd.DataFrame({ 60 "簡介" : jianjie_list, 61 "樓層" : louceng_list, 62 "規格" : guige_list, 63 "地址" : dz_list, 64 "房價" : fangjia_list, 65 "面積" : mianji_list, 66 }) 67 #儲存為csv文件 68 df.to_csv("fangzi.csv" , encoding='utf_8_sig', index=False)
爬取運行生成一個.csv文件
導入庫:
1 import numpy as np 2 import pandas as pd 3 import matplotlib.pyplot as plt 4 import seaborn as sns 5 import matplotlib.pyplot as plt 6 import seaborn as sns 7 fangzi = pd.DataFrame(pd.read_csv('fangzi.csv',encoding="utf-8")) 8 fangzi.head()
對數據進行清理:
1 fangzi.duplicated()
1 fangzi = fangzi.drop_duplicates() 2 fangzi.head() 3 #刪除重復值
1 fangzi['房價'].isnull().value_counts() 2 #判斷統計空值
1 fangzi['面積'].isnull().value_counts() 2 #判斷統計空值
1 fangzi['樓層'] = fangzi['樓層'].map(str.strip) 2 fangzi.head() 3 #填充缺失值
1 fangzi['樓層'] = fangzi['樓層'].map(str.strip) 2 fangzi['地址'] = fangzi['地址'].map(str.rstrip) 3 fangzi.head() 4 #空格處理
1 fangzi.describe() 2 #異常值處理
數據分析與可視化:
房屋面積占比分布所做的柱狀圖:
1 #導入庫 2 import numpy as np 3 import pandas as pd 4 import matplotlib.pyplot as plt 5 plt.rcParams['font.family'] = ['SimHei']#亂碼轉中文 6 s=pd.Series([246,134,49],['面積50+㎡','面積80+㎡','面積120+㎡']) #設置柱狀圖屬性 7 s.plot(kind = 'bar', title = '上海房屋面積分布值') #設置柱狀圖標題 8 plt.show() 9 #柱狀圖
房屋規格占比所做的餅圖:
1 df_score = fangzi['規格'].value_counts() #統計評分情況 2 plt.title("房子戶型規格占比圖") #設置餅圖標題 3 plt.figure(figsize=(80, 15))#設置圓餅圖比例 4 plt.rcParams['font.sans-serif'] = ['SimHei']#亂碼轉中文 5 plt.pie(df_score.values,labels = df_score.index,autopct='%1.1f%%') 6 #分布值餅圖
房屋面積規格所做的散點圖:
1 sns.regplot(x = '面積',y = '規格',data=fangzi)#設置散點圖屬性 2 sns.figure(figsize=(10, 5))#設置比例 3 #散點圖
完整代碼:
1 #導入庫 2 import requests 3 from lxml import etree 4 import time 5 import re 6 import pandas as pd 7 8 #初始化空列表 9 jianjie_list, louceng_list, guige_list, dz_list, fangjia_list, mianji_list = [], [], [], [], [], [] 10 11 for a in range(10): 12 #爬取前10頁的內容 13 url = "https://shanghai.qfang.com/sale/f{}".format(a*10) 14 15 #設置請求頭 16 headers = { 17 "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36" 18 } 19 #requests請求鏈接 20 resp = requests.get(url,headers=headers).text 21 22 #使用lxml模塊中的etree方法將字符串轉化為html標簽 23 html = etree.HTML(resp) 24 25 #xpath定位標簽 26 list = html.xpath("/html/body/div[4]/div/div[1]/div[4]/ul/li") 27 28 #爬取內容具體鏈接 29 for li in list: 30 #爬取簡介 31 jianjie = li.xpath("./div[2]/div[1]/a/text()")[0] 32 #爬取樓層 33 louceng = li.xpath("./div[2]/div[2]/p[4]/text()")[0] 34 #爬取規格 35 guige = li.xpath("./div[2]/div[2]/p[1]/text()")[0] 36 #爬取地址 37 dz = li.xpath("./div[2]/div[3]/div/text()")[0] 38 #爬取房價 39 fangjia = li.xpath("./div[3]/p[2]/text()")[0] 40 #爬取面積 41 mianji = li.xpath("./div[2]/div[2]/p[2]/text()")[0] 42 43 #輸出 44 print(jianjie) 45 print(louceng) 46 print(guige) 47 print(dz) 48 print(fangjia) 49 print(mianji) 50 # 將字段存入初始化的列表中 51 jianjie_list.append(jianjie) 52 louceng_list.append(louceng) 53 guige_list.append(guige) 54 dz_list.append(dz) 55 fangjia_list.append(fangjia) 56 mianji_list.append(mianji) 57 58 #pandas中的模塊將數據存入 59 df = pd.DataFrame({ 60 "簡介" : jianjie_list, 61 "樓層" : louceng_list, 62 "規格" : guige_list, 63 "地址" : dz_list, 64 "房價" : fangjia_list, 65 "面積" : mianji_list, 66 }) 67 #儲存為csv文件 68 df.to_csv("fangzi.csv" , encoding='utf_8_sig', index=False) 69 import numpy as np 70 import pandas as pd 71 import matplotlib.pyplot as plt 72 import seaborn as sns 73 import matplotlib.pyplot as plt 74 import seaborn as sns 75 fangzi = pd.DataFrame(pd.read_csv('fangzi.csv',encoding="utf-8")) 76 #csv文件 77 fangzi.head() 78 79 #數據清理 80 fangzi.duplicated() 81 82 #刪除重復值 83 fangzi = fangzi.drop_duplicates() 84 fangzi.head() 85 86 #判斷統計空值 87 fangzi['房價'].isnull().value_counts() 88 89 #判斷統計空值 90 fangzi['面積'].isnull().value_counts() 91 92 #判斷統計空值 93 fangzi['規格'].isnull().value_counts() 94 95 #填充缺失值 96 fangzi['樓層'] = fangzi['樓層'].map(str.strip) 97 fangzi.head() 98 99 #空格處理 100 fangzi['樓層'] = fangzi['樓層'].map(str.strip) 101 fangzi['地址'] = fangzi['地址'].map(str.rstrip) 102 fangzi.head() 103 104 #異常值處理 105 fangzi.describe() 106 107 108 import numpy as np 109 import pandas as pd 110 import matplotlib.pyplot as plt 111 plt.rcParams['font.family'] = ['SimHei']#亂碼轉中文 112 s=pd.Series([246,134,49],['面積50+㎡','面積80+㎡','面積120+㎡']) #設置柱狀圖屬性 113 s.plot(kind = 'bar', title = '上海房屋面積分布值') #設置柱狀圖標題 114 plt.show() 115 #柱狀圖 116 117 df_score = fangzi['規格'].value_counts() #統計評分情況 118 plt.title("房子戶型規格占比圖") #設置餅圖標題 119 plt.figure(figsize=(80, 15))#設置圓餅圖比例 120 plt.rcParams['font.sans-serif'] = ['SimHei']#亂碼轉中文 121 plt.pie(df_score.values,labels = df_score.index,autopct='%1.1f%%') 122 #圓餅圖 123 124 sns.regplot(x = '面積',y = '規格',data=fangzi)#設置散點圖屬性 125 sns.figure(figsize=(10, 5))#設置比例 126 #散點圖
總結:
經過數據爬取與數據可視化,我們了解到,除了虹口區以外各區的二手房均價都趨於緩和階段,規格多數為二室一廳的房屋。初步爬取分析達到預期,但相對數據對比感覺還不夠全面地達到效果。通過python這門課我自己完成了網絡爬蟲和數據可視性,繼續豐富了自己的能力。