链家房产网站北京二手房数据采集与分析_第1页
链家房产网站北京二手房数据采集与分析_第2页
链家房产网站北京二手房数据采集与分析_第3页
链家房产网站北京二手房数据采集与分析_第4页
链家房产网站北京二手房数据采集与分析_第5页
已阅读5页,还剩21页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

湖南商务职业技术学院毕业设计

目录

1引言1

1.1项目背景1

1.2开发环境与工具1

1.2.1Python简介1

1.2.2Pandas简介1

1.2.3Pyecharts简介2

2需求分析2

2.1可行性需求分析2

2.2采集目标功能分析2

2.3关键技术分析2

2.3.1网络爬虫技术2

2.3.2文件存取技术3

2.3.3可视化技术3

3数据采集3

3.1采集页面分析3

3.2反爬策略分析4

3.3多线程实现6

3.4翻页实现8

3.5解析房源信息9

3.6保存到json文件10

3.7运行爬虫程序10

4数据清洗与处理11

4.1数据清洗需求12

4.2数据读取与处理12

4.3数据清洗13

4.4数据清洗结果15

5数据统计与分析15

I

湖南商务职业技术学院毕业设计

5.1数据分析说明15

5.2数据展示15

5.2.1统计各区的房源数量和平均价格15

5.2.2统计不同朝向与楼层的房源数量与价格18

5.2.3统计各装修风格的数量20

5.2.4统计每年建造的房屋数量与价格21

5.3综述23

6小结23

参考资料24

II

湖南商务职业技术学院毕业设计

链家房产网站北京二手房数据采集与分析

1引言

北京作为中国的首都和经济中心,房地产市场一直备受关注。对于购房者

而言,了解房价走势、房源数量和房源质量是做出购房决策的重要参考因素。

而二手房市场则更加反映了房地产市场的真实情况,因此对于二手房市场的数

据采集和分析也具有很大的实用价值。

1.1项目背景

本毕业设计的目的是通过采集北京市二手房源数据,进行数据清洗、数据

分析和数据可视化,以获取二手房市场的实际情况和趋势,并为购房者提供决

策支持。在本毕业设计中,将使用requests、pandas、pyecharts和json等技

术,同时还要克服反爬虫措施,确保数据的可靠性和准确性。最终的目标是建

立一个完整的二手房市场数据分析平台,为购房者提供全面的市场信息,帮助

他们做出明智的购房决策。

1.2开发环境与工具

1.2.1Python简介

Python是一种简单易学、功能强大的编程语言,广泛应用于数据处理、人

工智能、Web开发等领域。Python具有清晰简洁的语法结构,使得编写代码变

得更加高效和愉悦。它拥有大量优秀的第三方库和工具,如numpy、pandas、

matplotlib等,可以方便地处理各种数据分析、可视化等任务。同时,Python

社区非常活跃,各种问题可以很容易地找到解决方案和支持。Python语言已经

成为许多人的首选编程语言,尤其是在数据科学和人工智能领域。

1.2.2Pandas简介

Pandas是一种开源的Python数据处理库,它是基于NumPy的扩展库,可

以用来处理各种数据格式,如CSV、Excel、SQL、JSON等。它提供了DataFrame

和Series这两个主要的数据结构,可以灵活地进行数据清洗、预处理、转换、

分析等操作。Pandas非常适合数据科学领域的工作,包括数据清洗和数据可视

化等任务。它的操作方式简单易学,是数据分析和机器学习的必备工具之一。

1

湖南商务职业技术学院毕业设计

1.2.3Pyecharts简介

Pyecharts是一款基于Python语言的数据可视化库,它能够帮助用户通过

简单的代码实现各种图表的绘制。该库内置了多种类型的图表,包括折线图、

柱状图、散点图、饼图等,并且支持对图表的样式、主题、数据等进行灵活的

定制。使用Pyecharts可以快速生成美观、直观的数据可视化图表,是Python

数据分析领域不可或缺的工具之一。

2需求分析

2.1可行性需求分析

1)技术可行性分析:

数据采集和分析是Python语言的优势之一,利用Python的requests库和

BeautifulSoup库可以轻松地从网页中爬取所需信息,使用Pandas库可以方便

地处理数据。此外,使用pyecharts库可以将数据可视化展示,为后续分析提

供便利。

2)经济可行性分析:

房地产市场是一个庞大的市场,其信息变化十分迅速,对于中介机构和房

产公司而言,获取市场信息非常重要。通过本项目,可以快速地获取北京地区

的二手房源数据,并对数据进行分析,提高市场分析的效率和准确性,降低信

息收集的成本。因此,本项目具有较高的经济可行性。

2.2采集目标功能分析

通过网络爬虫技术获取二手房源的相关信息,包括房源名称、位置、面积、

价格、房型、楼层、朝向等。将采集的数据存储到json文件中,方便后续的数

据处理和分析。对清洗后的数据进行分析,探索二手房源市场的价格走势、房

源分布情况、不同地区房价等信息。

2.3关键技术分析

2.3.1网络爬虫技术

网络爬虫是一种自动化程序,通过模拟用户访问行为,自动访问互联网上

的网站,并获取网站的数据。爬虫通常会遵守网站的协议和规则,如robots.txt

2

湖南商务职业技术学院毕业设计

文件,避免对目标网站造成过大的负担或损害。爬虫技术可以广泛应用于数据

采集、信息分析、搜索引擎、机器学习等领域。

2.3.2文件存取技术

JSON是一种轻量级的数据交换格式,易于阅读和编写,同时也易于机器解

析和生成。它基于JavaScript语法,但可用于多种编程语言。JSON数据结构

包含键值对,可以表示数字、字符串、布尔值、数组和对象等数据类型。在Web

开发中,JSON常用于前后端数据传输和API接口的设计。

2.3.3可视化技术

可视化技术是一种将数据转化为图形化界面以便更直观地展示数据的技

术。它可以帮助人们更好地理解数据,从而更好地做出决策。可视化技术可以

使用各种图形图表,例如柱状图、折线图、散点图等等,同时还可以使用各种

颜色、标签和交互方式来使数据更加生动和易于理解。常用的可视化工具包括

matplotlib、pyecharts、plotly等等。

3数据采集

3.1采集页面分析

通过浏览器打开链家网官网/ershoufang/,该网

站可以查询到北京全境的二手房信息,每页显示30条房源信息,选择栏中可以

筛选北京某个区的二手房源。链家网首页如下图3-1所示:

图3-1链家网首页

3

湖南商务职业技术学院毕业设计

本次数据采集的字段有房源名称、房源所在区、地址、户型、朝向、楼层、

建造年份、关注人数、发布时间、总价、每平米价格等。如下图3-2所示:

图3-2房源各个字段

其中“房源所在区“字段没有直接显示在房源标签html文档中,需要通过

区域筛选栏选择不同的区,在对各个区域发起请求时保存“房源所在区”字段。

每个区的名称和url保存在html中,如下图3-3所示:

图3-3北京各个区的名称和url

在筛选栏中选择“东城”并确认,页面返回了东城所有的二手房源信息和

总套数,根据二手房源总套数和每页只显示30条记录的策略可以确定总页数,

从而制定页面翻页逻辑。如下图3-4所示:

图3-4每个区域二手房总套数

根据上述采集页面的分析,现在已经基本确定了页面采集的方式和流程,

首先对首页发起get请求,从响应中解析出北京每个区的名称和url,并逐个

对各个区进行处理,在处理时保存各个区的名称;根据每个区的二手房源总套

数计算总页数,进而进行翻页处理。

3.2反爬策略分析

对网站进行初步分析发现,该网站的数据量比较大,如果在爬虫程序中没

有制定合理的反爬策略就很难全量采集到二手房源数据。Ip封禁是大多数网站

常用并且有效的反爬策略,如果同一个ip在短时间内对网站发起了大量的请

4

湖南商务职业技术学院毕业设计

求,该网站就会认为这是爬虫程序,从而封禁此ip。通过大量的测试发现该网

站存在封ip的情况,大量请求之后网站会弹出人机验证页,如下图3-5所示:

图3-5人机认证页

出现这种情况需要立马更换ip才能继续发起请求。本项目使用ip代理更

换ip,首先需要到快代理网站申请一个代理api链接,对这个代理api每发起

一次请求就会返回一个新的ip地址,然后在使用这个ip地址即可。如下图3-6

所示:

图3-6申请代理api链接

在爬虫程序中在对目标url发起请求时就不能直接使用requests.get方法

了。需要封装一个change_ip_request方法,该方法首先对目标url发起请求,

判断响应内容,如果响应内容中包含了”人机验证”就使用代理api更换ip地

址重新对目标url发起请求,该方法的返回response对象,以供后续方法调用

和解析response。change_ip_request方法如下所示:

5

湖南商务职业技术学院毕业设计

#如果ip被封,则更换新ip继续请求

defchange_ip_request(self,url):

headers={'User-Agent':random.choice(self.USER_AGENTS)}

response=requests.get(url,headers=headers,verify=True)

if"人机认证"inresponse.text:

#使用ip代理

ip=

requests.get('/api/getdps/?secret_id=ovczrvb9z9lhk3oayy5j&num=1&signat

ure=omshi1knto9n2i40rsk47gq9ps&pt=1&sep=1')

proxies={'http':'http://'+ip.text}

print("更换ip地址"+str(ip.text)+"")

response=requests.get(url,headers=headers,proxies=proxies,verify=True)

print(response.text)

returnresponse

通过大量测试发现,仅仅只更换ip地址是不能突破网站限制的,还需要随

机更换请求头。在爬虫代码中构建了一个请求头列表池,在使用requests发起

请求随机到池中选址一个请求头,这样才能保证爬虫能够正常运行。请求头列

表池如下所示:

def__init__(self):

self.USER_AGENTS=[

"Mozilla/5.0(WindowsNT10.0;Win64;x64)AppleWebKit/537.36(KHTML,

likeGecko)Chrome/58.0.3029.110Safari/537.36Edge/16.16299",

"Mozilla/5.0(WindowsNT6.1;WOW64)AppleWebKit/537.36(KHTML,like

Gecko)Chrome/50.0.2661.102Safari/537.36",

"Mozilla/5.0(WindowsNT6.1;WOW64;rv:54.0)Gecko/20100101Firefox/54.0",

"Mozilla/5.0(Macintosh;IntelMacOSX10_12_6)AppleWebKit/537.36

(KHTML,likeGecko)Chrome/61.0.3163.100Safari/537.36",

"Mozilla/5.0(Macintosh;IntelMacOSX10_12_6)AppleWebKit/604.1.38

(KHTML,likeGecko)Version/11.0Safari/604.1.38",

"Mozilla/5.0(X11;Ubuntu;Linuxx86_64;rv:55.0)Gecko/20100101

Firefox/55.0",

"Mozilla/5.0(WindowsNT6.1;WOW64)AppleWebKit/537.36(KHTML,like

Gecko)Chrome/61.0.3163.79Safari/537.36"]

3.3多线程实现

为了提高数据采集的效率,在程序中使用了多线程。Python多线程是指在

一个Python进程中同时运行多个线程,每个线程执行不同的任务,以达到并发

执行的效果。在Python中可以通过使用threading模块来创建多线程。该模

块提供了一个Thread类,可以通过创建该类的实例来创建线程。

6

湖南商务职业技术学院毕业设计

在开启多线程之前需要拿到北京各个区的url链接,而后对每个区开启一

个线程。使用get_area_items方法获取每个区的名称url链接。详细代码如下

所示:

defget_area_items(self,start_url):

response=self.change_ip_request(start_url)

html=etree.HTML(response.text)

area_items=html.xpath('/html/body/div[3]/div/div[1]/dl[2]/dd/div[1]/div/a')

method=lambdax:{'area':x.xpath('./text()')[0],'url':''+

x.xpath('./@href')[0]}

area_items_dic=list(map(method,area_items))

print(area_items_dic)

self.request_area(area_items_dic)

首先使用xpath方法获取到每个区所在的a标签列表,在使用map方法和

lambda表达式处理a标签,将区名称和区url以字段的方式保存到列表中,最

后调用request_area方法以多线程的方法分别对各个区进行处理。多线程处理

方法如下所示:

defrequest_area(self,area_items_dic):

Thread=[]

forarea_iteminarea_items_dic:

area=area_item['area']

url=area_item['url']

#创建线程

t1=threading.Thread(target=self.next_page,args=(url,area,1,))

Thread.append(t1)

#开启所有线程

fortinThread:

t.start()

#等待结束所有线程

fortinThread:

t.join()

具体来说,该函数接受一个包含地区和对应链接的字典列表

area_items_dic,遍历列表中每个字典元素,获取地区和链接,并为每个地区

创建一个线程进行爬取。在循环中,使用threading.Thread()方法创建一个

线程对象t1,并将self.next_page()方法作为目标函数传入,同时也将url、

area和1作为参数传入。这个1是当前的页数,该参数可以方便后续翻页的

处理。接着将线程对象t1添加到Thread列表中。这样,每次循环都会创建

一个线程,并将其添加到列表中。

7

湖南商务职业技术学院毕业设计

在循环结束后,使用for循环遍历Thread列表,对其中的每个线程对象

调用start()方法,以开启所有线程,使它们并发执行。接着,再次使用for

循环遍历Thread列表,并对其中的每个线程对象调用join()方法,以等待

所有线程执行完毕,确保所有线程的爬取任务都已经完成。

3.4翻页实现

函数next_page(),它实现了在链家网站中爬取指定区域的房产数据,并

实现了翻页功能。具体来说,该函数接收三个参数:url、area和page,其中

url表示该区域的链接,area表示该区域的名称,page表示当前爬取的页数。

详细代码如下所示:

defnext_page(self,url,area,page):

response=self.change_ip_request(url+'/pg'+str(page))

print(response.url)

html=etree.HTML(response.text)

max_page_num=

int(''.join(html.xpath('//*[@id="content"]/div[1]/div[2]/h2/span/text()')))/30

self.get_house_detail(response,area)

ifpage<=max_page_num+1:

print("======正在采集"+area+"的数据,第"+str(page)+"页

======")

page+=1

self.next_page(url,area,page)

该函数首先通过self.change_ip_request()方法发送请求,并使用

etree.HTML()方法解析HTML页面。接着,通过XPath表达式获取该区域的

最大页数max_page_num,并使用self.get_house_detail()方法对该页的房

产数据进行采集。如果当前页数page小于等于最大页数max_page_num+1,

则将page加1,然后递归调用next_page()方法,以继续爬取该区域的下一

页数据。

需要注意的是,由于递归调用会导致函数的栈帧不断增加,因此在爬取大

量数据时,可能会出现栈溢出的情况。为了避免这种情况的发生,可以考虑使

用非递归的方式实现翻页功能,或者使用尾递归优化等技术来减少函数调用的

栈帧使用。此外,在爬取数据时,还需要注意处理可能出现的异常情况,例如

网络连接失败、HTML页面解析失败等情况。

8

湖南商务职业技术学院毕业设计

3.5解析房源信息

使用get_house_detail()方法解析链家网的二手房源数据,并将数据保存

到文件中。具体来说,该函数接收两个参数:response和area,其中response

表示从链家网站中获取到的HTTP响应对象,area表示该区域的名称。详细代

码如下所示:

defget_house_detail(self,response,area):

html=etree.HTML(response.text)

house_items=html.xpath('//*[@id="content"]/div[1]/ul/li')

result={}

forhouse_iteminhouse_items:

house_name=house_item.xpath('./div[1]/div[1]/a/text()')

address1=house_item.xpath('./div[1]/div[2]/div/a[1]/text()')

address2=house_item.xpath('./div[1]/div[2]/div/a[2]/text()')

house_info=house_item.xpath('./div/div[3]/div/text()')

follow_info=house_item.xpath('./div/div[4]/text()')

price_all=house_item.xpath('.//div[@class="priceInfo"]/div/span/text()')

price_unit=house_item.xpath('.//div[@class="priceInfo"]/div[2]/span/text()')

result['house_name']=''.join(house_name)

result['area']=area

result['address1']=''.join(address1)

result['address2']=''.join(address2)

result['house_info']=''.join(house_info)

result['follow_info']=''.join(follow_info)

result['price_all']=''.join(price_all)

result['price_unit']=''.join(price_unit)

print(result)

self.saveData(result)

该函数首先使用etree.HTML()方法解析HTML页面,并使用XPath表达

式获取到该页面中所有的房产数据。然后,使用循环遍历每一个房产数据,通

过XPath表达式获取该房产的各个属性,例如房屋名称、地址、房屋信息、关

注信息、总价和单价等。接着,将这些属性组成一个字典result,并打印输出

该字典,以方便调试和查看数据。最后,将该字典保存到文件中,通过

self.saveData()方法实现。

需要注意的是,由于链家网站的HTML页面结构可能会发生变化,因此需

要定期更新XPath表达式,以保证程序能够正确地获取房产数据。此外,在爬

取数据时,还需要注意处理可能出现的异常情况,例如XPath解析失败、字典

9

湖南商务职业技术学院毕业设计

保存失败等情况。

3.6保存到json文件

将获取到的数据使用saveData方法保存到json文件中。具体来说,该函

数接收一个参数result,该参数表示获取到的单个房产数据,是一个Python

字典类型。详细代码如下所示:

defsaveData(self,result):

json_str=json.dumps(result,ensure_ascii=False)

withopen("house.json","a",encoding="utf-8")asf:

f.write(json_str+"\n")

该函数首先使用json.dumps()方法将该字典转换成JSON字符串,设置

ensure_ascii=False参数可以保证输出的JSON中文字符不会被转义。然后,

使用withopen()语句打开文件house.json,将JSON字符串写入文件中。

由于爬取到的数据可能很大,因此使用追加模式"a",每次将数据添加到文件

的末尾,而不是覆盖之前的数据。需要注意的是,在保存数据时,还需要考虑

异常处理和线程安全的问题。例如,当写入文件时出现异常,需要进行错误处

理,以避免程序崩溃。此外,由于多个线程可能会同时访问同一个文件,因此

需要确保写入文件时的线程安全性,可以使用锁机制或者将写入文件的操作放

在同步块中,以保证每次只有一个线程能够写入文件。

3.7运行爬虫程序

使用run方法启动爬虫,将url传入给get_area_items方法。详细代码如

下所示:

defrun(self,start_url):

self.get_area_items(start_url)

Main方法如下所示:

if__name__=='__main__':

spider=Spider()

spider.run('/ershoufang/')

程序运行日志如下图3-7所示:

10

湖南商务职业技术学院毕业设计

图3-7程序运行日志

程序运行结束之后会在当前路径下生成house.json文件,打开文件可以发

现已经采集了2万4千多条记录,已经满足了数据分析与可视化的要求。如下

图3-8所示:

图3-8house.json文件

本项目json作为数据传输和处理格式,具有以下优点:易于解析:JSON是

一种基于文本的格式,易于解析和处理。Python中可以使用json模块解析和

生成JSON格式数据,操作简单;结构化:JSON格式可以表示复杂的数据结构;

可读性好:JSON数据的格式结构非常清晰,易于阅读和理解;支持多种编程语

言:由于JSON是一种开放的数据格式,支持多种编程语言。因此,JSON数据

可以轻松地在不同的系统之间进行交换和共享,实现数据的互通性。

4数据清洗与处理

数据清洗是数据预处理中重要的步骤之一,它是指对原始数据进行筛选、

整理、转换、填充等一系列操作,以达到消除数据噪声、提高数据质量、减少

数据冗余、适应数据分析模型等目的的过程。数据清洗可以使得数据更加规整,

更符合数据分析模型的要求,有利于进行数据挖掘等任务,从而挖掘出更多有

价值的信息。综上所述,数据清洗是数据预处理中至关重要的一个环节,可以

提高数据质量、减少冗余、适应分析模型等,从而帮助我们更好地挖掘数据背

后的价值。本项目数据清洗使用Python中的numpy和pandas库进行处理。

11

湖南商务职业技术学院毕业设计

4.1数据清洗需求

1)使用pandas库的read_json()函数读取house.json文件

2)从house_info字段中解析出户型、面积、朝向、装修风格、楼层、建造年

份、建筑结构。将楼层拆分成两个字段楼层和具有楼层,如“低楼层(共11

层)“处理后为两个字段”低楼层“和”11“。剔除建造年份字段中多余

的字符串,如“1991年建“处理后”1991“,如果house_info字段中没有

建造年份则用“0000“代替。

3)从follow_info字段中解析出关注人数、发布天数,剔除其中多余的字符

串,比如“1人关注”处理后“1”。然后根据发布天数计算出发布日期。

4)由于price_all字段是房屋的总价,而该字段的单位是“元/平”,明显单

位存在问题,所以将“元/平”替换成“万”。

4.2数据读取与处理

创建check_json_file,用于读取一个JSON文件,并检查文件中每个JSON

对象的格式。函数的作用是读取JSON文件中的数据,并将格式正确的数据转换

为DataFrame格式。在读取JSON文件的过程中,函数会跳过格式不正确的数据。

如果某个JSON对象的格式正确,那么该对象将被添加到一个列表中,并最终转

换为DataFrame格式返回。

defcheck_json_file(input_file):

#用于存储格式正确的json数据

json_data_list=[]

#打开输入文件

withopen(input_file,'r',encoding='utf-8')asf:

forlineinf:

try:

#将每一行json数据转换成python对象

json_data=json.loads(line.strip())

if'年建'notinjson_data['house_info']:

house_info_li=str(json_data['house_info']).split('|')

structure=house_info_li[-1]

house_info_pre=house_info_li[:-1]

12

湖南商务职业技术学院毕业设计

house_info_pre.append("0000年建")

house_info_pre.append(structure)

json_data['house_info']='|'.join(house_info_pre)

#检查json数据格式是否正确

if'house_name'injson_dataand'area'injson_dataand'address1'injson_data

and'address2'injson_dataand'house_info'injson_dataand'follow_info'injson_dataand

'price_all'injson_dataand'price_unit'injson_data:

#将格式正确的json数据添加到列表中

json_data_list.append(json_data)

except:

#如果转换失败或者格式不正确则跳过该行数据

pass

#将列表中的json数据转换成DataFrame格式

df=pd.DataFrame(json_data_list)

returndf

该函数还有一个重要功能,就是处理house_info中的房屋建造年份字段。

House_info字段有两种格式,第一种包含了房屋建造年份字段,而第二种没有

包含,在后续使用pandas清洗数据时,这两种情况需要编写两个不同的正则表

达式,这两个正则表达式不能同时被应用,用其他方式处理也及其复杂。所有

在读取house.json文件时就将house_info字段的长度统一。

统一house_info字段长度的具体逻辑如下:首先检查JSON对象中名为

"house_info"的字符串是否包含"年建"这个子字符串。如果不包含,代码将使

用"|"字符作为分隔符,将"house_info"字段拆分为一个列表。然后,代码将获

取列表中的最后一个元素,并将其赋值给变量"structure"。接下来,代码将创

建一个新的"house_info_pre"列表,该列表包含原始列表中除了最后一个元素

之外的所有元素,并在末尾添加了一个字符串"0000年建",然后将

"structure"变量添加到列表的末尾。最后,代码将使用"|"字符将新的

"house_info_pre"列表合并成一个字符串,并将其赋值回JSON对象的

"house_info"字段。

4.3数据清洗

本项目数据清洗主要使用pandas来完成。Pandas是一个开源的Python数

13

湖南商务职业技术学院毕业设计

据分析库,提供了灵活高效的数据结构和数据分析工具,非常适合进行数据清

洗和预处理。

创建data_clean方法并传入Dataframe对象,读取Dataframe的house_info

列,从其中解析出户型、面积、朝向、装修风格、楼层、建造年份、建筑结构

字段,编写正则表达式并使用str.extract()函数从字符串列中提取特定的信

息。详细代码如下所示:

str_contain_year='(\d+室\d+厅)\|([\d.]+)平米\|(.+)\|([^]+)\|(.+)\|(\d+)年建\|(.+)'

li_contain_year=['type','size','direction','decoration','floor','year','structure']

df[li_contain_year]=df['house_info'].str.extract(str_contain_year)

df=df.drop('house_info',axis=1)

将楼层字段拆分成两个字段:floor_level和floor_all,并删除原有的楼

层字段;清洗"year"字段中的冗余字符串"年建";从follow_info字段中解析

出关注人数、发布天数。详细代码如下所示:

#将楼层拆分成两个字段楼层和具有楼层

df[['floor_level','floor_all']]=df['floor'].str.extract('(.+)\(共(\d+)层\)')

df=df.drop('floor',axis=1)

#剔除建造年份字段中多余的字符串

df['year']=df['year'].apply(lambdax:re.sub(r'年建','',x)iftype(x)==strelse'0000')

#从follow_info字段中解析出关注人数、发布天数

df[['follow_num','post_time']]=df['follow_info'].str.extract('(\d+)人关注/([^]+)发布')

df=df.drop('follow_info',axis=1)

根据发布天数计算出发布日期;将price_all字段的单位由“元/平”替换

成“万”。最后将清洗后的数据保存到json文件中。详细代码如下所示:

#根据发布天数计算出发布日期

df['post_date']=df['post_time'].apply(calculate_date)

#将price_all字段的单位由“元/平”替换成“万”

df['price_all']=df['price_all'].str.replace('元/平','万')

df['price_unit']=df['price_unit'].str.replace('元/平','元')

#将清洗后的数据保存为house_clean.json

df.to_json('house_clean.json',orient='records',lines=True,force_ascii=False)

14

湖南商务职业技术学院毕业设计

4.4数据清洗结果

运行check_json_file方法和data_clean方法进行数据清洗。代码如下所

示:

df=check_json_file('house.json')

data_clean(df)

程序运行结束之后会到本地创建一个house_clean.json文件,其文件内容

如下图所示:

图4-1数据清洗结果

从数据清洗结果文件中可以看到house_info字段和floor字段被正确解析

了。后续通过pandas读取该文件即可进行数据的统计与分析。

5数据统计与分析

5.1数据分析说明

数据分析使用pandas来完成,Pandas是一个Python数据处理库,它提供

了高性能、易于使用的数据结构和数据分析工具,能够轻松处理各种数据类型

和来源,是Python生态系统中的一个重要组成部分。Pandas提供了一系列数

据分析函数,可以帮助用户对数据进行统计分析、聚合操作等。比如,用户可

以使用groupby()函数对数据进行分组操作;使用describe()函数对数据进行

基本统计分析;使用apply()函数对数据进行自定义操作等。

5.2数据展示

5.2.1统计各区的房源数量和平均价格

读取一个名为"house_clean.json"的JSON文件,并将其中的房源数据

转换为一个PandasDataFrame对象。对DataFrame进行一些数据清洗操作,

15

湖南商务职业技术学院毕业设计

如将'price_unit'字段中的单位“元”去除,并将其中的逗号替换为小数点。

对'area'字段进行分组统计,得到每个区域的房源数量和平均单价。使用

pyecharts库中的Map类创建一个地图对象,将房源数量和平均单价数据分别

添加到地图上。设置地图的全局选项,如标题、视觉映射选项等。最后将地图

保存为一个HTML文件。详细代码如下所示:

importjson,re

importpandasaspd

frompyecharts.chartsimportMap

frompyechartsimportoptionsasopts

#读取JSON文件

withopen('house_clean.json','r',encoding='gbk')asf:

houses=[json.loads(line)forlineinf.readlines()]

#转换为DataFrame

df=pd.DataFrame(houses)

df['price_unit']=df['price_unit'].map(lambdax:float(str(x).replace('元','').replace(',','.')))

#根据area字段分组统计house_name的数量和price_unit的平均价格

result=df.groupby('area').agg({'house_name':'count','price_unit':'mean'}).reset_index()

result.columns=['area','count','mean_price_unit']

result['mean_price_unit']=result['mean_price_unit'].map(lambdax:round(x))

result['area']=result['area'].map(lambdax:str(x)+'区')

#绘制地图

map=(

Map()

.add(

series_name='房源数量',

data_pair=[list(z)forzinzip(result['area'],result['count'])],

maptype='北京',

label_opts=opts.LabelOpts(is_show=True,font_size=10)

)

.add(

series_name='平均单价',

16

湖南商务职业技术学院毕业设计

data_pair=list(zip(result['area'],result['mean_price_unit'])),

maptype='北京',

label_opts=opts.LabelOpts(is_show=False)

)

.set_global_opts(

title_opts=opts.TitleOpts(title='北京市房源分布'),

visualmap_opts=opts.VisualMapOpts(

max_=max(result['count']),

range_color=['#fff','#00BFFF','#00FA9A','#FFD700','#FF8C00','#FF0000'],

)))

#保存为HTML文件

map.render('beijing_map.html')

运行结果如下图所示:

图5-1北京市地图

北京市的房价整体上呈现区域性分布,从平均价格单位来看,东城区、西

城区和海淀区属于高房价区,分别为114、129和102万元/平方米,且这些区

域的二手房数量相对较少,说明这些区域的房价相对较高且供给较为紧张。北

京市的中等房价区主要分布在丰台区、石景山区和昌平区,二手房的平均价格

17

湖南商务职业技术学院毕业设计

分别为61、54和48万元/平方米,且这些区域的二手房数量相对较多,说明这

些区域的房价相对较为平稳,供求相对平衡。北京市的低房价区主要分布在大

兴区、通州区和怀柔区,二手房的平均价格分别为44、44和30元/平方米,且

这些区域的二手房数量相对较多,说明这些区域的房价相对较低且供给相对充

足。综上所述,北京市的房价整体呈现出明显的区域性分布,不同区域的房价

和二手房数量有着明显的差异,投资者在购买房产时应该综合考虑各方面因素,

以选择适合自己的房产投资方案。

5.2.2统计不同朝向与楼层的房源数量与价格

使用了pandas和pyecharts库来读取一个JSON文件并绘制柱状图。首先,

代码使用pandas的read_json()方法读取一个名为house_clean.json的JSON

文件,其中lines=True参数表示每一行都是一个JSON对象。然后,代码使用

str.strip()方法剔除了direction字段中的空格,并使用map()方法将

price_unit字段中的字符串类型转换为浮点型,去掉了单位和千位分隔符。

接下来,代码使用groupby()方法将数据按照floor_level字段进行分组,

然后使用agg()方法对每个组内的数据进行统计,其中count表示数量,mean

表示平均值。最后,代码使用reset_index()方法将分组后的数据重新设置索

引。接着,代码使用pyecharts库的Bar()类创建一个柱状图对象。使用

add_xaxis()方法添加x轴数据,使用add_yaxis()方法添加y轴数据,并使用

set_global_opts()方法设置全局参数,例如标题和x轴名称。

importpandasaspd

frompyecharts.chartsimportBar

frompyechartsimportoptionsasopts

#读取json文件

df=pd.read_json('house_clean.json',lines=True)

#剔除direction中的空格

df['direction']=df['direction'].str.strip()

df['price_unit']=df['price_unit'].map(lambdax:float(str(x).replace('元','').replace(',','.')))

#根据floor_level分组,求数量和price_unit平均价格

grouped=df.groupby('floor_level').agg({'house_name':'count','price_unit':

'mean'}).reset_index()

grouped['price_unit']=grouped['price_unit'].map(lambdax:round(x))

18

湖南商务职业技术学院毕业设计

#绘制柱状图

bar_chart=(

Bar()

.add_xaxis(list(grouped['floor_level']))

.add_yaxis("数量",list(grouped['house_name']))

.add_yaxis("平均价格",list(round(grouped['price_unit'],2)))

.set_global_opts(

title_opts=opts.TitleOpts(title="按楼层分组统计"),

xaxis_opts=opts.AxisOpts(name="楼层"),

))

bar_chart.render('柱状图.html')

图5-2柱状图

从平均价格单位来看,地下室的二手房平均价格最高,为68万元/平方米,

其次是低楼层和顶层,分别为66和57万元/平方米,这可能是因为地下室的房

屋位置特殊,且拥有更好的采光条件;而低楼层和顶层则可能因为存在噪音、

采光、通风等方面的问题,导致其价格相对较低。从二手房数量来看,中楼层

的二手房数量最多,达到了6706套,其次是高楼层和低楼层,分别为3904和

3597套,这可能是因为中楼层的位置相对较为舒适,采光、通风等方面的条件

较好。总体来说,不同楼层的二手房价格和数量都有一定的差异,投资者在购

买房产时应该综合考虑各方面因素,以选择适合自己的楼层投资方案。

19

湖南商务职业技术学院毕业设计

5.2.3统计各装修风格的数量

使用Pandas的read_json函数读取一个名为"house_clean.json"的JSON

格式文件,并将其转换为一个DataFrame对象df。对DataFrame中的

"price_unit"列进行数据清洗,将其中的"元"字符剔除并将逗号替换为小数点,

最终转换为float类型。使用groupby函数对DataFrame对象df按照

"decoration"列进行分组,统计每组中"house_name"的数量,并计算每组中

"price_unit"的平均值。使用Pyecharts中的Pie()函数创建一个饼图对象,

通过add方法将数据添加到饼图中,设置全局选项和系列选项,最后使用render

方法将饼图保存到名为"饼图.html"的文件中。

importpandasaspd

frompyecharts.chartsimportPie

frompyechartsimportoptionsasopts

#读取json文件

df=pd.read_json('house_clean.json',lines=True)

#剔除price_unit中的“元”字符并将逗号替换成.

df['price_unit']=df['price_unit'].str.replace('元','').str.replace(',','').astype(float)

#根据decoration分组,求数量和price_unit平均价格

grouped=df.groupby('decoration').agg({'house_name':'count'}).reset_index()

#绘制饼图

pie_chart=(

Pie()

.add("数量",[list(z)forzinzip(grouped['decoration'],list(grouped['house_name']))])

.set_global_opts(

title_opts=opts.TitleOpts(title="按装修程度分组统计",padding=10),

legend_opts=opts.LegendOpts(orient="vertical",

pos_left="left",padding=70,item_width=10,item_height=10)

).set_series_opts(label_opts=opts.LabelOpts(formatter="{b}:{c}")))

pie_chart.render('饼图.html')

20

湖南商务职业技术学院毕业设计

图5-3饼图

从数量来看,精装二手房数量最多,达到了11505套,其次是简装和其他,

分别为8844和3200套,而毛坯二手房数量最少,为761套。在当前的房地产

市场,二手房市场上,精装房屋的销售较为受欢迎,可能是因为精装房屋已经

在内部装修和装饰方面花费了大量的人力和物力,从而为购房者提供了更好的

住宿体验。在购买二手房时,装修风格也是一个非常重要的因素,购房者需要

根据自己的需求和喜好来选择不同的装修风格,以满足自己的住宿需求。

5.2.4统计每年建造的房屋数量与价格

使用pyecharts库,通过对读取的数据进行一些处理和统计,绘制了一个

折线图。具体地,代码首先读取了一个JSON文件house_clean.json,然后使

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论