一、选题背景
因为深圳经济非常不错,想必想要去深圳工作的人也不少。衣食住行是生活的基本需求。衣和食好解决,不喜欢的衣服可以买新的,不好吃的食物可以换一家吃。可是在住宿上,买房和租房的置换成本都相对较高,因此房源选择尤为慎重。作为目前买不起房的人自然是以租房为主,但是租房我们一般是通过中介或者是网站来实现租房的需求。以我通过python以行政区为单位,对比分析各行政区房源数量分布情况的爬起,就可以可视化的去比较多个房源对于租房也更有利,可以说是更快更方便的找到各个方面都符合自己心意房子。
二、主题式网络爬虫设计方案
1.主题式网络爬虫名称
深圳各个区域租房信息爬取
2.主题式网络爬虫爬取的内容与数据特征分析
D盘中有一文件“house_info.csv”保存了租房信息数据,该文件来自“https://sz.zufun.cn”以该文件作为数据源,按以下要求进行分析:
导入数据并对数据进行预处理;
分析各行政区的房源分布情况;
以小区为单位,分析各小区的房源数量;
对整个租房数据的户型进行分析;
分析租房数据的租金分布情况;
3.主题式网络爬虫设计方案概述(包括实现思路与技术难点)
思路:查看网页的结构,定位目标数据的位置,爬取数据,将数据进行清洗,最后将清洗后的数据进行可视化。
难点:如何解决数据分析缺少模块,如何爬取多个页面的数据,请求异常的处理
三、主题页面的结构特征分析
1.主题页面的结构与特征分析
目标内容界面:
2.Htmls 页面解析
3.节点(标签)查找方法与遍历方法
打开网页的源码,然后用鼠标检查工具找打对应大概位置进行查找,先找大标签,再找其中的小标签。
我们这里把要获取的数据找着之后,然后在元素中对应位置分析。(如图对应的就是元素中“div.guess.header”)
四、网络爬虫程序设计
1.数据爬取与采集
以下为爬取流程图
以下为爬取过程的代码
1). 导入数据
1 import pandas as pd 2 import numpy as np 3 detail = pd.read_csv(r"D:\house_info.csv", encoding="utf-8") 4 5 # print(detail.head()) 6 7 print("清洗前缺失值的数目:\n",detail.isnull().sum()) 8 9 # 删除detail的缺失值 10 11 d1 = detail.dropna(axis=0, how="any") 12 13 # 以d1 为数据源 14 15 # print(d1) 16 17 print("清洗后缺失值的数目:\n",d1.isnull().sum()) 18 19 # 从前向后查找和判断是否有重复值 20 21 print("重复值:",d1.duplicated().sum())
运行后得出
2). 各行政区房源分布
1 area = set(d1["位置1"]) 2 3 # 统计多少个行政区 4 5 print(area) 6 7 # 创建一个DataFrame 对象,筛选需要数据{行政区,房源数量} 8 9 d2 = pd.DataFrame({'行政区':d1["位置1"].unique(),'房源数量':[0]*len(area)}) 10 print(d2) 11 print('-'*20) 12 13 # groupby统计房源数量,并从小到大排序 14 15 groupby_area = d1.groupby(by="位置1").count() 16 print(groupby_area) 17 d2["房源数量"] = groupby_area.values 18 d2 = d2.sort_values(by=["房源数量"],ascending=True) 19 print(d2)
运行后得出
3). 小区房源数量TOP10
1 area_small = set(d1["小区"]) 2 3 # 统计多少个小区 4 5 # print(area_small) 6 7 # 创建一个DataFrame 对象,筛选需要数据{小区,小区房源数量} 8 9 d_samll = pd.DataFrame({"小区":d1["小区"].unique(),"小区房源数量":[0]*len(area_small) }) 10 print(d_samll) 11 print('-'*40) 12 13 # groupby统计小区房源数量,并从大到小排序 14 15 groupby_area = d1.groupby(by="小区").count() 16 17 # print(groupby_area) 18 19 d_samll["小区房源数量"] = groupby_area.values 20 d_samll = d_samll.sort_values(by=["小区房源数量"],ascending=False) 21 print(d_samll) 22 d_top10 = d_samll.head(10) 23 24 # 取前十 25 26 print("小区房源数量TOP10是:\n",d_top10)
运行截图如下
4). 户型TOP10分布
1 house_type = set(d1["户型"]) 2 3 # 统计多少个户型 4 5 print(house_type) 6 7 8 # 创建一个DataFrame 对象,筛选需要数据{户型,户型数量} 9 d_house = pd.DataFrame({"户型":d1["户型"].unique(),"户型数量":[0]*len(house_type) }) 10 print(d_house) 11 print('-'*40) 12 13 14 # groupby统计户型数量,并从大到小排序 15 groupby_area = d1.groupby(by="户型").count() 16 print(groupby_area) 17 d_house["户型数量"] = groupby_area.values 18 d_house = d_house.sort_values(by=["户型数量"],ascending=False) 19 print(d_house) 20 d_top10 = d_house.head(10) 21 # 取前十 22 print("户型数量TOP10是:\n",d_top10)
运行得出
5). 租金分布
1 house_rent = set(d1["价格"]) 2 3 # 统计多少个价格 4 5 # print(house_rent) 6 7 8 # 创建一个DataFrame 对象,筛选需要数据{价格,价格数量} 9 d_rent = pd.DataFrame({"租金":d1["价格"].unique(),"价格数量":[0]*len(house_rent) }) 10 print(d_rent) 11 print('-'*40) 12 13 14 # groupby统计价格数量,并从大到小排序 15 groupby_area = d1.groupby(by="价格").count() 16 print(groupby_area) 17 d_rent["价格数量"] = groupby_area.values 18 d_rent = d_rent.sort_values(by=["价格数量"],ascending=False) 19 print(d_rent) 20 d_top10 = d_rent.head(10) 21 # 取前十 22 print("价格数量TOP10是:\n",d_top10)
运行得出
1 # 对每个行政区,进行租金价格平均分析 2 3 4 # 新建一个DataFrame对象,设置房租总金额和总面积初始值为0 5 6 print(area) 7 avg_rent = pd.DataFrame({'行政区':d1["位置1"].unique(),'房租总金额':[0]*len(area),'总面积':[0]*len(area) }) 8 print(avg_rent) 9 print('-'*40) 10 11 12 13 # 求总金额和总面积 14 sum_price = d1["价格"].groupby(d1["位置1"]).sum() 15 sum_area = d1["面积"].groupby(d1["位置1"]).sum() 16 avg_rent["房租总金额"] = sum_price.values 17 avg_rent["总面积"] = sum_area.values 18 print(avg_rent) 19 20 21 22 # 计算各区域每平方米房租价格,并保留2位小数 23 avg_rent['每平方米租金(元)'] = round(avg_rent['房租总金额']/avg_rent['总面积'],2) 24 print(avg_rent) 25 print("*-"*25) 26 27 28 # 合并需要的数据 29 rent_merge = pd.merge(d2,avg_rent) 30 rent_merge 31 32 # print(rent_merge)
运行结果如下
house_info.csv的部分如下
4.数据分析与可视化
1).各行政区房源分布柱形图
代码如下
1 # 绘图 2 3 4 import matplotlib.pyplot as plt 5 import matplotlib 6 matplotlib.rcParams['font.sans-serif']=['SimHei'] 7 matplotlib.rcParams['axes.unicode_minus']=False 8 9 10 X = d2["行政区"] 11 print(X) 12 Y = d2["房源数量"] 13 print(Y) 14 plt.figure(figsize=(8,6),dpi=300) 15 plt.bar(X, Y, width=0.5, linewidth=2) 16 17 18 for i,j in zip(X, Y): 19 plt.text(i, j, "%d" % j, fontsize=16) 20 plt.xlabel("行政区") 21 plt.ylabel("房源数量") 22 plt.title("各行政区房源分布图") 23 plt.show() 24 25 26 #这里选用柱形图是因为柱形图可以直观的展示结果
运行结果如下
从数据可以看出:从行政区的福田区到龙岗区,房源的数量是逐渐增加的。
2).小区房源数量TOP10柱形图
代码如下
1 # 绘图 2 3 4 import matplotlib.pyplot as plt 5 import matplotlib 6 matplotlib.rcParams['font.sans-serif']=['SimHei'] 7 matplotlib.rcParams['axes.unicode_minus']=False 8 9 X = d_top10["小区"] 10 print(X) 11 Y = d_top10["小区房源数量"] 12 print(Y) 13 plt.figure(figsize=(8,6),dpi=300) 14 plt.bar(X, Y, width=0.5, linewidth=2) 15 16 17 for i,j in zip(X, Y): 18 plt.text(i, j, "%d" % j, fontsize=12) 19 plt.xlabel("小区") 20 plt.ylabel("小区房源数量") 21 plt.title("小区房源数量TOP10") 22 plt.xticks(rotation=335) 23 plt.savefig(r"C:\Users\烤小鹅\Desktop\小区房源数量TOP10.png",dpi=400) 24 plt.show()
运行结果如下
从图可知,小区的房源数量从 丰湖花园到 名仕阁逐渐递减,而且丰湖花园小区房源是其他小区的两倍左右,丰湖花园的房源很多,在该竞争领域很大优势。
3). 户型TOP10分布
1 # 绘图 2 3 4 import matplotlib.pyplot as plt 5 import matplotlib 6 matplotlib.rcParams['font.sans-serif']=['SimHei'] 7 matplotlib.rcParams['axes.unicode_minus']=False 8 9 X = d_top10["户型"] 10 11 # print(X) 12 13 Y = d_top10["户型数量"] 14 15 # print(Y) 16 17 plt.figure(figsize=(12,8),dpi=300) 18 19 # plt.bar(X, Y, width=0.5, linewidth=2) 20 21 b = plt.barh(X, Y, height=0.6, linewidth=1) 22 23 for i in b: 24 plt.text(i.get_width(),i.get_y()+0.2,i.get_width() ) 25 plt.ylabel("户型") 26 plt.xlabel("户型数量") 27 plt.title("户型数量TOP10") 28 plt.savefig(r"C:\Users\烤小鹅\Desktop\户型数量TOP10.png",dpi=400) 29 plt.show()
运行结果如下
从图可知,众多户型中 5室1卫户型数量远远超过其他户型,可以看出这个户型是很多购买者喜欢的。
4). 租金分布
1 import matplotlib 2 import matplotlib.pyplot as plt 3 import matplotlib.ticker as mtick 4 from matplotlib.font_manager import FontProperties 5 matplotlib.rcParams['font.sans-serif']=['SimHei'] 6 matplotlib.rcParams['axes.unicode_minus']=False 7 num = rent_merge['房源数量'] 8 # 数量 9 10 11 price = rent_merge['每平方米租金(元)'] 12 # 价格 13 14 15 X = rent_merge["行政区"] 16 print(X) 17 18 19 # Y = rent_merge["房源数量"] 20 # print(Y) 21 fig = plt.figure(figsize=(8,6)) 22 axl = fig.add_subplot(111) 23 axl.plot(X, price,'or-',label = '价格') 24 axl.set_ylim([0,210]) 25 axl.set_ylabel('价格')、 26 27 28 for i,j in zip(X, price): 29 plt.text(i, j, "%d" % j, fontsize=16) 30 plt.title("租金分布情况") 31 ax2 = axl.twinx() 32 plt.bar(X,num,width=0.4,color = 'green',label = '数量', linewidth=2) 33 ax2.set_ylabel('数量') 34 ax2.set_ylim([0,2000]) 35 for i,j in zip(X, num): 36 plt.text(i, j, "%d" % j, fontsize=16) 37 plt.title("租金分布情况") 38 plt.savefig(r"C:\Users\烤小鹅\Desktop\租金分布情况图.png",dpi=400) 39 plt.show()
运行结果如下
从折线图可以看出,罗湖区与南山区 房源数量比较多,但是租金价格平均是高的,龙岗区的房源数量多而且租金相比其他行政区是价廉的,适合毕业生、求职者去租房。
5.数据持久化
以下为数据持久化代码
1 import requests 2 from bs4 import BeautifulSoup 3 import sqlite3 4 import pandas as pd 5 6 url = "https://datachart.500.com/dlt/history/newinc/history.php?limit=100&sort=0" 7 8 response = requests.get(url) 9 if response.status_code == 200: 10 print("请求成功") 11 12 soup = BeautifulSoup(response.content, 'html.parser') 13 table = soup.find('div', attrs={"class": 'chart'}) 14 rows = table.find_all('tr') 15 16 data = [] 17 for row in rows: 18 cells = row.find_all('td') 19 if len(cells) == 15: 20 date = cells[0].text 21 Front_Area_1 = cells[1].text 22 # ... 继续提取其他数据 23 24 25 data.append([date, Front_Area_1, ...]) 26 27 df = pd.DataFrame(data, columns=['期号', '前区号码1', ...]) 28 29 30 # 连接到SQLite数据库 31 conn = sqlite3.connect('lottery_data.db') 32 cursor = conn.cursor() 33 34 35 # 创建表 36 create_table_query = ''' 37 CREATE TABLE IF NOT EXISTS lottery ( 38 id INTEGER PRIMARY KEY AUTOINCREMENT, 39 价格 TEXT, 40 面积 TEXT, 41 编号 TEXT, 42 户型 TEXT, 43 楼层 TEXT, 44 位置1 TEXT, 45 位置2 TEXT, 46 小区 TEXT, 47 地铁 TEXT, 48 49 50 ); 51 ''' 52 cursor.execute(create_table_query) 53 54 55 # 插入数据 56 insert_query = 'INSERT INTO lottery (期号, 前区号码1, 前区号码2, ..., 开奖日期) VALUES (?, ?, ?, ..., ?);' 57 cursor.executemany(insert_query, df.values.tolist()) 58 59 60 # 提交事务并关闭连接 61 conn.commit() 62 conn.close() 63 64 print("数据已保存到数据库") 65 else: 66 print("请求失败")
6.将以上各部分的代码汇总,附上完整程序代码
(1)爬虫代码部分
(2)可视化代码部分
(3)数据持久化代码
五、总结以及遇到的问题
对本课程设计的整体完成情况做一个总结,通过这次利用python代码爬虫爬取网站数据并分析,得出(1).从行政区的福田区到龙岗区,房源的数量是逐渐增加的。(2).小区的房源数量从 丰湖花园到 名仕阁逐渐递减,而且丰湖花园小区房源是其他小区的两倍左右,丰湖花园的房源很多,在该竞争领域很大优势。(3).众多户型中 5室1卫户型数量远远超过其他户型,可以看出这个户型是很多购买者喜欢的。(4)从折线图可以看出,罗湖区与南山区 房源数量比较多,但是租金价格平均是高的,龙岗区的房源数量多而且租金相比其他行政区是价廉的,适合毕业生、求职者去租房。所以要是想要到深圳就业就可以考虑在龙岗区租房子,价格实惠,而且房源数量也很多。
这让我掌握了最基础的数据分析知识,体验了数据分析的乐趣,包括数据预处理,异常值的查找等,数据的合并和分组及聚合,还有数据可视化来直观的观察,分析数据,更加直观的获得自己想要的信息,也变得更加便捷。同样大多数人面临这样一个挑战:我们认识到数据可视化的必要性,但缺乏数据可视化方面的专业技能。部分原因可以归结于,数据可视化只是数据分析过程中的一个环节,数据分析师可能将精力花在获取数据、清洗整理数据、分析数据、建立模型。
问题:由于anaconda之前下载的版本问题,数据分析运行时缺少很多模块,根本运行不出来,我在cmd中用“pip list”查询模块想看看缺少什么模块,但是查询出来的结果并不乐观,可以说是基本上的模块都没有,想要安装运行所需要的模块也一直是安装失败。在查询“python”表示是安装成功,说明不是python的问题。之后在网上查询了才知道是我的anaconda版本问题。我将原本的anaconda彻底卸载(如果没有彻底卸载新安装的其他版本的anaconda也是不能使用的)通过“清华大学开源镜像网站”,重新下载了anaconda3-2021.11版本,之后再在cmd中查询现有的模块,但是还是缺少了两个模块,根据上网所查的知识安装了所需模块。折腾了许久之后终于解决了运行问题。
标签:数据分析,plt,python,户型,爬虫,房源,rent,print,数量 From: https://www.cnblogs.com/zxyq/p/17471002.html