赞
踩
MongoDB是文档数据库,采用BSON的结构来存储数据。
在文档中可嵌套其他文档类型,使得MongoDB具有很强的数据描述能力。
本节案例使用的数据为链家的租房信息,源数据来自于链家网站,所以首先要获取网页数据并解析出本案例所需要的房源信息,然后将解析后的数据存储到MongoDB中,最后基于这些数据进行城市租房信息的查询和聚合分析等。
OS:Ubuntu16.04
Python3
MongoDB:v3.4.20
安装本实验所需依赖库
下载方式:
python3 -m pip install pymongo -i https://pypi.tuna.tsinghua.edu.cn/simple
python3 -m pip install requests -i https://pypi.tuna.tsinghua.edu.cn/simple
python3 -m pip install lxml -i https://pypi.tuna.tsinghua.edu.cn/simple
python3 -m pip install matplotlib==3.0.0 -i https://pypi.tuna.tsinghua.edu.cn/simple
分析租房信息首先要获取原始的房源数据,本例使用python爬虫技术获取链家网页的新房楼盘信息。如图所示,对房源信息进行分析需要获取房源所在区域、小区名、房型、面积、具体位置、价格等信息。
1.使用Python的requests爬虫库从链家网站上获取各城市的楼盘信息,并用lxml库来解析网页上的数据。
import requests
import re
from lxml import html
res = requests.get(url, headers=headers)
content = html.fromstring(res.text)
使用requests库的get方法获取网页内容,第一个参数为爬取的网页地址,第二个参数为get请求的头header。Get方法返回的是html格式的网页内容,使用lxml库对html网页格式化。
2.获取网页上具体字段信息时使用xpath函数解析html标签,如获取某城市所有的区域信息:
areas = content.xpath('//div[@class="filter-by-area-container"]/ul[@class="district-wrapper"]/li/text()')
使用xpath方法从html文档中来查找信息,具体参数格式请参考lxml库文档,这里不作介绍。
3.获取房源信息后,设计文档的存储格式如下:
{
"_id" : ObjectId("5c1aebe52ca2902f3cd00c4a"),
"area" : "汉南",
"title" : "绿地城",
"type" : "住宅",
"square" : "建面 87-135㎡",
"detail_area" : "汉南其它",
"detail_place" : "马影河大道(汉洪高速汉南出口处)",
"price" : 9400
}
id由系统自动生成,所在区域area、小区名称title、住房类型type等为字符串形式,价格为浮点数。
4.Python连接数据库需要使用到pymongdb库,连接数据库和创建集合的代码片段如下:
import pymongodb
client = MongoClient('localhost', 27017)
db = client.get_database("lianjia")
col = db.get_collection("loupan")
使用MongoClient类创建连接数据库对象client,本案例使用本地数据库localhost:27017。get_database方法连接数据库,参数lianjia为数据库名,get_collection方法连接集合,参数loupan为集合名称,如果不存在此数据库和集合则新建。本例中爬取城市武汉的租房信息,集合名称为“loupan”,如需其他城市信息可设置URL,
5.网页解析出的源数据需存入MongoDB文档中,可使用单条插入的方式,也可以使用批量插入的方式。使用的函数均为insert()。如下代码展示向文档插入单条房源信息:
item = { "area": area, "title": title, "type": type, "square": square, "detail_area": detail_area, "detail_place": detail_place, "price": int(price), } col.insert(item)
6.数据存储后可根据不同条件查询数据;如查询该城市有多少个区域,每个区域有多少房源。实现代码如下:
col.distinct("area") #查询该城市有多少个区域
col. find({'area':'江岸'}).count() #某个区域有多少房源
col. find({'area':'青山'}) #查找某区域所有的房源信息
房源数据进行存储后,需要进行数据分析,比如获取每个区域房价的平均值和最大值,并以条形图的形式展示出来。
1.以统计每个区域的房价为例,使用MongoDB聚合管道技术对数据进行分组计算,如下代码片段对房源的区域进行分组聚合:
pipeline = [ {"$group": { "_id": "$area", "avgPrice": {"$avg": "$price"} , "MaxPrice": {"$max" : "$price"} } }, ] col.aggregate(pipeline)
此聚合使用group分组操作符对区域
a
r
e
a
进
行
聚
合
,
计
算
区
域
楼
盘
价
格
的
平
均
值
和
最
大
值
,
area进行聚合,计算区域楼盘价格的平均值和最大值,
area进行聚合,计算区域楼盘价格的平均值和最大值,avg根据分组数据进行求取房价平均值,$max根据分组获取房租最大值。聚合结果如下所示:
{ “_id” : “黄冈”, “avgPrice” : 0, “MaxPrice” : 0 }
{ “_id” : “鄂州”, “avgPrice” : 6250, “MaxPrice” : 11000 }
{ “_id” : “洪山”, “avgPrice” : 5343.0, “MaxPrice” : 45000 }
{ “_id” : “汉阳”, “avgPrice” : 5694.1, “MaxPrice” : 47000 }
{ “_id” : “东湖高新”, “avgPrice” : 5031.5, “MaxPrice” : 40000 }
{ “_id” : “咸宁”, “avgPrice” : 10000, “MaxPrice” : 10000 }
{ “_id” : “青山”, “avgPrice” : 5375, “MaxPrice” : 28000 }
{ “_id” : “武昌”, “avgPrice” : 7996.7, “MaxPrice” : 57000 }
{ “_id” : “东西湖”, “avgPrice” : 4083.9, “MaxPrice” : 40000 }
{ “_id” : “硚口”, “avgPrice” : 9036.1, “MaxPrice” : 70000 }
{ “_id” : “沌口开发区”, “avgPrice” : 5055.0, “MaxPrice” : 45000 }
{ “_id” : “黄陂”, “avgPrice” : 3199.7, “MaxPrice” : 40000 }
{ “_id” : “新洲”, “avgPrice” : 1675.8, “MaxPrice” : 26000 }
{ “_id” : “江汉”, “avgPrice” : 9441.1, “MaxPrice” : 85000 }
{ “_id” : “黄石”, “avgPrice” : 6380, “MaxPrice” : 8900 }
{ “_id” : “江岸”, “avgPrice” : 6774.0, “MaxPrice” : 48000 }
{ “_id” : “江夏”, “avgPrice” : 2749.3, “MaxPrice” : 35000 }
{ “_id” : “蔡甸”, “avgPrice” : 3965.6, “MaxPrice” : 32000 }
{ “_id” : “汉南”, “avgPrice” : 3451.8, “MaxPrice” : 18000 }
上述结果可以看到此聚合计算出来的平均房价和最高房价显示与实际不符,在武汉,江汉和江岸区的房价实际上是咸宁地区的房价高很多的,此聚合得出此结果的原因是有些楼盘的价格待定,数据库里price值为0,还有些楼盘是商业的或别墅,价格定位不一样,这都导致最终的平均值不对,因此接下来对进行过滤后再统计房租。
2.以下代码展示匹配楼盘类型为住宅,已给出房价的楼盘信息:
pipeline = [ {"$match": { "type": "住宅", "price": {"$ne": 0} } },#过滤掉房价待定且不是住宅用途的楼盘 {"$group": { "_id": "$area", "avgPrice": {"$avg": "$price"}, "MaxPrice": {"$max": "$price"} } }, ] col.aggregate(pipeline)
使用match操作符数据进行过滤,过滤出符合条件的租房信息后再使用group功能进行分组统计,得出的结果为:
{ “_id” : “鄂州”, “avgPrice” : 8833.333333333334, “MaxPrice” : 10000 }
{ “_id” : “洪山”, “avgPrice” : 20662.5, “MaxPrice” : 32000 }
{ “_id” : “汉阳”, “avgPrice” : 17877.7, “MaxPrice” : 29000 }
{ “_id” : “东湖高新”, “avgPrice” : 19607.5, “MaxPrice” : 27500 }
{ “_id” : “青山”, “avgPrice” : 24333.3, “MaxPrice” : 28000 }
{ “_id” : “武昌”, “avgPrice” : 31760, “MaxPrice” : 39000 }
{ “_id” : “东西湖”, “avgPrice” : 15353.3, “MaxPrice” : 18500 }
{ “_id” : “硚口”, “avgPrice” : 23371.4, “MaxPrice” : 39000 }
{ “_id” : “沌口开发区”, “avgPrice” : 15100, “MaxPrice” : 17000 }
{ “_id” : “黄陂”, “avgPrice” : 10600, “MaxPrice” : 12500 }
{ “_id” : “新洲”, “avgPrice” : 7120, “MaxPrice” : 9200 }
{ “_id” : “江汉”, “avgPrice” : 30076.9, “MaxPrice” : 38000 }
{ “_id” : “黄石”, “avgPrice” : 7975, “MaxPrice” : 8900 }
{ “_id” : “江岸”, “avgPrice” : 25050, “MaxPrice” : 42000 }
{ “_id” : “江夏”, “avgPrice” : 11666.6, “MaxPrice” : 14500 }
{ “_id” : “蔡甸”, “avgPrice” : 9660, “MaxPrice” : 12500 }
{ “_id” : “汉南”, “avgPrice” : 7775, “MaxPrice” : 9500 }
3.基于聚合统计出的数据使用python绘制条形图,使用到matplotlib库,具体代码参考代码清单的rentAnaly.py文件,展示出的结果如图所示:
附代码
wget http://10.90.3.2/HUP/NoSQL/WinQSB/pyloupan.py
wget http://10.90.3.2/HUP/NoSQL/WinQSB/loupanAnaly.py
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。