利用Python来协助姑妈买房!Python“买”房比她自己买便宜二十万
1、python基础
python是一种面向对象、解释型*语言,语法简洁清晰、基础代码库丰富,覆盖网络、文件、gui、数据库、文本等领域。并能和其他主流语言沟通协助制作。python主要分为cpython、jpython、ironpython、pypy等。解释型语言可移植行好,但是运行速度不及编译型语言,其次解释型语言源码无法像编译型那样编译成二进制串加密。
1.1.2 linux
安装python3.x.x,通过pip安装需要的第三方库。
1.2 python库
python为开发者提供丰富代码库,开发者从不会从零开始开发,基础功能基本已经有现成的成熟的框架或库支持,因此大幅度的提升开发者的开发效率和提高代码健壮性。
python很容易学!小编有弄一个交流,互问互答,资源共享的交流学习基地,如果你也是python的学习者或者大牛都欢迎你来!㪊:548+377+875!一起 学习共同进步!
深圳房价飞涨,但也阻挡不了祖国各地人民来深圳买房的欲望。深圳房价动辄几百万,程序猿这种动物想在深圳安居压力山大。所以买房必然是人生一重大决定,必须货比三家。当前各种房产中介,各种开发商,各种楼盘。信息多到我们无法掌握。因此程序猿就需要利用专业的优势通过一些方式获取有效数据,分析筛选最优秀的房源。
2.1.1 python教你买房维度指标体系
python教你买房首先我们需要确定我们购房时最关注的维度体系和指标体系。关注主要维度和关键指标体系如图所示:
python教你买房,分为数据爬虫和大数据分析。首先通过爬虫方式获取到深圳房产交易网成功交易量和交易价格并得出深圳房价的趋势,得到最合适的购房时间段,确认最佳的上车时间。然后爬取链家网数据并按用户关注维度深度分析帅选得出适宜的房子,做好一切上车的准备。
2.1.2 python教你买房框架
python教你买房框架,主要分为5块,分别为主程序模块、代理ip模块、地图服务模块、可视化服务模块、目标页面模块等。主程序为首先启动代理ip模块,抓取带来ip并通过测试可用代理ip存入到代理池,定时线程定时清洗带来并把无效的带来ip剔除出代理池,代理ip模块并提供外部api获取代理ip。主程序通过代理服务访问并抓取外部网页的有效信息并在主程序模块理解习html并写入到本地文件。主程序会调用地图服务获取经纬度信息,并绘制热力图等。同时间可视化模块定时读取文件并生成可视化图形报表供业务侧分析使用。
1、主服务模块
主程块通过api提供给前端用户登录和获取用户交互输入,通过参数解析获取得到用户的需求组装请求,获取代理ip转发请求到目标地址获取目标数据,返回数据通过html解析得到有效数据写入到文件地图服务和可视化服务生产友好的图形报表,辅佐得出python教你买房的数据支撑。
2、ip代理服务模块
#!/usr/bin/env python3# -*- coding: utf-8 -*-# function:定时抓取免费代理ip,并检查可用性,可用proxy存入数据库供业务方调用获取# author:elideng# date: 2017-11-11import requestsfrom bs4 import beautifulsoupimport tracebackimport pymysqlimport threadingimport time'''
*@function【爬取ipproxy】
*@request: 请求 [in]
* param1 int ireqgetnum: 请求获取代理量
*@response:响应 [out]
* param1 int ifinalgetnum: 最终获取代理量
*@return:返回值 int : 0(成功) 其它失败
'''def grabipproxy():
arriplist = []
user_agent = 'mozilla/5.0 (windows nt 6.3; wow64; rv:43.0) gecko/20100101 firefox/43.0'
header = {}
header['user-agent'] = user_agent #url = 'http://www.xicidaili.com/nn/1'
url = 'http://www.baidu.com'
res = requests.get(url, headers=header) if res.status_code == 200:
info = {}
soup = beautifulsoup(res.text, 'lxml')
ips = soup.findall('tr') for x in range(1, len(ips)):
ip = ips[x]
tds = ip.findall("td")
ip_port = tds[1].contents[0] + ":" + tds[2].contents[0]
arriplist.append(ip_port) #后续加上代理可用校验,非可用踢出代理池
#print(ip_port)
#计算列表量
return arriplist'''
*@function【测试ipproxy是否可用】
*@request: 请求 [in]
* param1 string desurl: 测试目的地址
* param2 string ipproxy:代理ip端口
* param3 int itimeout:超时时间
* param4 string feature:目的地址特征
*@response:响应 [out]
* param1 int ifinalgetnum: 最终获取代理量
*@return:返回值 :成功返回代理proxy 失败返回空
'''def checkproxyip(desurl, ipproxy, itimeout=3, feature=""): #确认带来ipaddress 2秒内能否
#desurl = 'http://www.baidu.com'
header = {'user-agent': 'mozilla/5.0 (windows nt 6.3; wow64; rv:43.0) gecko/20100101 firefox/43.0'}
proxies = {'http': 'http://' + ipproxy} #组装代理
res = none # 声明
exmsg = none
try: #res = requests.get(url=desurl, headers=header, proxies=proxies, timeout=itimeout)
res = requests.get(desurl, proxies=proxies, timeout=itimeout) # 代理方式请求,防止反爬虫
soup = beautifulsoup(res.text, 'lxml') #feature=""
#print(soup.findall(feature))
except:
exmsg = '* ' + traceback.format_exc() if exmsg: return -1
if res.status_code != 200: return -1
if res.text.find(feature) < 0: return -1
return 0#更新代理池ipdef updateproxy(ipproxy, vaildflag="n"):
smysql = pymysql.connect(host='127.0.0.1', user='root', passwd='elideng', db='test')
cursor = smysql.cursor() try:
cursor.execute('update t_proxy set fvaildflag="%s" where fproxy="%s" limit 1' % (ipproxy, vaildflag))
smysql.commit() #提交执行
except:
smysql.rollback()
smysql.close() return 0#新增代理池ipdef insertproxy(ipproxy, vaildflag="y"):
smysql = pymysql.connect(host='127.0.0.1', user='root', passwd='elideng', db='test')
cursor = smysql.cursor() try:
cursor.execute('insert into t_proxy values("%s", "%s", now(), now())' % (ipproxy, vaildflag))
smysql.commit() #提交执行
except:
smysql.rollback()
smysql.close() return 0#获取proxydef getproxy(proxynum):
smysql = pymysql.connect(host='127.0.0.1', user='root', passwd='elideng', db='test')
cursor = smysql.cursor()
proxylist=[] try: if proxynum == -1:
cursor.execute('select fproxy from t_proxy where fvaildflag='y'') else:
cursor.execute('select fproxy from t_proxy where fvaildflag='y' limit %s' % (proxynum))
results = cursor.fetchall() for row in results:
proxylist.append(row[0]) except: # rollback in case there is any error
smysql.rollback()
smysql.close() return proxylistdef checkipproxytimer():
arriplist = []
arriplist = getproxy(-1) #获取代理池全量有效代理ip
#测试地址
#feature = 'xxx' #目标网页的特征码, 暂时不启用
desurl = "http://www.baidu.com"
for ipproxy in arriplist:
ires = checkproxyip(desurl, ipproxy) if ires: #proxy验证通过
setproxy(ipproxy, "y") else:
setproxy(ipproxy, "n") #失效无效代理if __name__ == '__main__': #0、爬取免费代理ip
grabipproxy() #1、启动定时线程,定时测试并清洗数据库代理ip
timer = threading.timer(3600, checkipproxytimer)
timer.start() #2、设置定时器失效时间
time.sleep(5)
timer.cancel() #5秒后停止定时器,程序可一直执行
3、地图服务模块
#!/usr/bin/env python3# -*- coding: utf-8 -*-# author:elideng# date: 2017-11-08from urllib.request import urlopen, quoteimport jsonfrom bs4 import beautifulsoupimport os#根据地址获取经纬度def getlnglat(address):
url = 'http://api.map.baidu.com/geocoder/v2/'
output = 'json'
ak = 'atzu2rqfrfoqcimvg9mvgm9bxchxjlyl'
add = quote(address) #由于本文地址变量为中文,为防止乱码,先用quote进行编码
uri = url + '?' + 'address=' + add + '&output=' + output + '&ak=' + ak
req = urlopen(uri)
res = req.read().decode()
temp = json.loads(res)
lat=0
lng=0
if 0 == temp['status']:
lat=temp['result']['location']['lat']
lng=temp['result']['location']['lng'] return lat,lng#根据两个经纬度计算距离def getplacedistance():
return 0#根据两个地点计算各类交通时间def getplacetime():
return 0def drawheatchart(date):
file = open("data.js", "a+") #data.js
file.seek(3) # 定位到第0行
file.writelines(date) #写入源数据到热力图源文件
file.close() return 0if __name__ == '__main__':
heatchartsrcfile = input('输入热力图源文件:') #data.js
drawheatchart(heatchartsrcfile)
<!doctype html><html><head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<script
src="https://code.jquery.com/jquery-3.2.1.min.js"
integrity="sha256-hwg4gsxgfzhoseeamdoygbf13fyquitwlaqgxvsngt4="
crossorigin="anonymous"></script>
<script type="text/javascript" src="http://api.map.baidu.com/api?v=2.0&ak=dd279b2a90afdf0ae7a3796787a0742e"></script>
<script type="text/javascript" src="http://api.map.baidu.com/library/heatmap/2.0/src/heatmap_min.js"></script>
<script type="text/javascript" src="./data.js"></script>
<title>热力图功能示例</title>
<style type="text/css"> ul,li{list-style: none;margin:0;padding:0;float:left;} html{height:100%} body{height:100%;margin:0px;padding:0px;font-family:"微软雅黑";} #container{height:500px;width:100%;} #r-result{width:100%;} </style></head><body>
<div id="container"></div>
<div id="r-result">
<input type="button" onclick="openheatmap();" value="显示热力图"/><input type="button" onclick="closeheatmap();" value="关闭热力图"/>
</div></body><script type="text/javascript">
var map = new bmap.map("container"); // 创建地图实例
var point = new bmap.point(114.061087, 22.528578); //自定义地图中点
map.centerandzoom(point, 12); // 初始化地图,设置中心点坐标和地图级别
map.enablescrollwheelzoom(); // 允许滚轮缩放
if(!issupportcanvas()){
alert('热力图目前只支持有canvas支持的浏览器,您所使用的浏览器不能使用热力图功能~')
}
heatmapoverlay = new bmaplib.heatmapoverlay({"radius":20});
map.addoverlay(heatmapoverlay); var param = {data:window.points,max:100}; //读取data.js热力源数据并生成热力图
console.log(param);
heatmapoverlay.setdataset(param); //是否显示热力图
function openheatmap(){
heatmapoverlay.show();
} function closeheatmap(){
heatmapoverlay.hide();
settimeout(function(){
location.reload();
}, 10000)
}
closeheatmap(); function setgradient(){ var gradient = {}; var colors = document.queryselectorall("input[type='color']");
colors = [].slice.call(colors,0);
colors.foreach(function(ele){
gradient[ele.getattribute("data-key")] = ele.value;
});
heatmapoverlay.setoptions({"gradient":gradient});
} //判断浏览区是否支持canvas
function issupportcanvas(){ var elem = document.createelement('canvas'); return !!(elem.getcontext && elem.getcontext('2d'));
}</script></html>
4、可视化模块
#!/usr/bin/env python3# -*- coding: utf-8 -*-# function:可视化服务# author:elideng# date: 2017-11-05import pandas as pdimport numpy as npimport matplotlib.pyplot as pltimport plotlyimport plotly.plotly as pyimport plotly.graph_objs as go
plotly.tools.set_credentials_file(username='elideng', api_key='tsc3809760')#雷达图显示房屋关注指标def drawradarmap(chartname, arrlables, arrdata, labelnum):
#数据校验
if labelnum < 0 or labelnum >10: return -1
if len(arrlables) != labelnum or len(arrdata) != labelnum: return -2
#=======自己设置开始============
#标签
labels = np.array(arrlables) #数据
data = np.array(arrdata) #========自己设置结束============
angles = np.linspace(0, 2*np.pi, labelnum, endpoint=false)
data = np.concatenate((data, [data[0]])) # 闭合
angles = np.concatenate((angles, [angles[0]])) # 闭合
fig = plt.figure()
ax = fig.add_subplot(111, polar=true) # polar参数!!
ax.plot(angles, data, 'bo-', linewidth=2) # 画线
ax.fill(angles, data, facecolor='r', alpha=0.25)# 填充
ax.set_thetagrids(angles * 180/np.pi, labels, fontproperties="simhei")
ax.set_title(chartname, va='bottom', fontproperties="simhei")
ax.set_rlim(0,10)
ax.grid(true)
plt.show()#皮尔逊作图def drawpearson():
return 0
2.1.3 python教你买房系列
1、网页观察
首先确定爬取链家网深圳房源,确定起始地址http://sz.lianjia.com。通过上一页和下一页完整的url比较组装符合筛选条件的房源链接。通过chrom的开发者工具的network,并把preserve log勾选,清空filter后刷新网页,观察网页html代码。
2、网页爬取
通过python3的requests库提供的http请求get/post通用方法模拟浏览器请求生成所有符合规则的url放入到队列,并循环请求符合要求的房源信息。请求响应html通过beautifulsoup解析html,并通过find_all配合正则表达式提取到html有效数据并写入到文件待分析。
3、多线程
爬虫最终目标就是爬取到更多符合用户需求的数据,如果单线程执行,抓取效率有限,因此爬虫需要加上多线程机制。多线程的实现方式有多种,如thread,threading,multithreading,其中thread偏底层,threading对thread进行了一定封装。python实现多线程的方式有两种函数或类包装。
#多线程方式
for i in generate_allurl(user_in_nub, user_in_city): #获取某城市
print(i) for url in get_allurl(i):
my_thread = threading.thread(target=main, args=(url, arriplist))
my_thread.start() print(url)
my_thread.join() print("current has %d threads" % (threading.activecount() - 1)) #当前存活线程
#线程池方式
pool.map(main, [url for url in get_allurl(i)])
4、headers设置
为避开反爬虫策略,后端请求需要模拟用户正常用户从浏览器请求,因此需要添加请求头。设置方式如下:
header = {'accept': '*/*', 'accept-language': 'en-us,en;q=0.8', 'cache-control': 'max-age=0', 'user-agent': 'mozilla/5.0 (x11; linux x86_64) applewebkit/537.36 (khtml, like gecko) chrome/48.0.2564.116 safari/537.36', 'connection': 'keep-alive', 'referer': 'http://www.baidu.com/'}
res = requests.get(url, headers=header)
5、session设置
6、ip代理池
爬虫出现就诞生了反爬虫,反爬虫的出现就催生了反反爬虫,哲学家黑格尔说过存在就是合理。因此很多技术就是在抗衡中逐渐成长。链家网是有反爬虫ip*机制,为了防止反爬虫链接网限制爬取到更多数据样本帮助与分析。因此采用ip代理池的方式,每次请求都随机获取ip和端口访问外部网站。获取ip代理池的方式有付费的和免费的方式可自行网上抓取并分析。
proxies={"http":"http://10.14.36.109:8080"}res = requests.get(url, headers=header, proxies=proxies)
7、监控
爬虫抓取是一个耗时较长的工程,因此需要添加监控,定时上报抓取进度到业务方,确认整个爬虫程序是否正常执行。//todo
2.2数据分析 //todo
大数据时代的网络爬虫爬取到有效信息,需要经过反复清洗、加工、统计、分析、建模等处理方法。数据分析是整合有效信息并详细研究和概括形成结论的过程。在实用中,数据分析可帮助人们作出判断,以便采取适当行动。
2.2.1 深圳购房词云分析
根据链家爬取样3199条待售房源,买卖二手房产我们最关系的参数指标词云图。如图所示我们最关注的满五牛,户型方正等。在购房的的时候我们可以按此词云图详细了解每个需要我们关注的参数指标,心有成竹。
#词云图def drawwordcloud(filename):
d = path.dirname(__file__) # read the whole text.
text = open(path.join(d, filename), encoding='utf-8').read() # generate a word cloud image 中文必须指定本地中文编码
wordcloud = wordcloud(font_path="c:windowsfontssimsun.ttc", width=2400, height=1800).generate(text) # display the generated image:
plt.imshow(wordcloud)
plt.axis("off") # lower max_font_size
wordcloud = wordcloud(max_font_size=40).generate(text)
plt.figure()
plt.imshow(wordcloud)
plt.axis("off")
plt.show()
2.2.2 深圳房源维度分析
深圳房源按多维度分析成交量/成交价趋势和皮尔逊系数分析;放盘量和反叛价分析;房源内部参数(如2.1.1)量化分析,房源外部参数量化分析等方式。最终解释我们购房时比较关心问题如怎么买的心仪的好房,何时是买房最好的时机等。
2.2.3 深圳房源数据模型
2.2.4 深圳房源均价热力模型
如图展示深圳深圳房源均价热力模型。//todo 待分析
2.2.5 深圳房源均价涨速热力模型
//todo 确定涨速最快,最具投资价值的区域,数据来源官网深圳房地产信息系统:http://ris.szpl.gov.cn/default.aspx
2.2.6 深圳房源成交量热力模型
//todo
2.2.7 深圳房源成交量热力模型
2.2.8 深圳房源成交量和成交价皮尔逊系数
//todo 计算皮尔逊系数,确定量价比关系,确认深圳房源当前状态和预测接下来可能的情况(有价有市,有市无价,有价无市),判断当前是否改上车。
2.2.9 深圳房屋内部指数量化雷达图模型
深圳房屋雷达图分析,程序首先会爬取到海量深圳待售的房产信息,等级差=(最高值-最低值)/10的方式把均价,实际使用率,梯户比例,楼层,楼间距等指标划分10等分,然后用户输入自己心仪的房子,程序将计算改房子的指标在海量房产中的雷达位置,帮助用户快速了解心仪房产的参数配置。效果图如下:
#雷达图显示房屋关注指标def drawradarmap(chartname, arrlables, arrdata, labelnum):
#数据校验
if labelnum < 0 or labelnum >10: return -1
if len(arrlables) != labelnum or len(arrdata) != labelnum: return -2
#=======自己设置开始============
#标签
labels = np.array(arrlables) #数据
data = np.array(arrdata) #========自己设置结束============
angles = np.linspace(0, 2*np.pi, labelnum, endpoint=false)
data = np.concatenate((data, [data[0]])) # 闭合
angles = np.concatenate((angles, [angles[0]])) # 闭合
fig = plt.figure()
ax = fig.add_subplot(111, polar=true) # polar参数!!
ax.plot(angles, data, 'bo-', linewidth=2) # 画线
ax.fill(angles, data, facecolor='r', alpha=0.25)# 填充
ax.set_thetagrids(angles * 180/np.pi, labels, fontproperties="simhei")
ax.set_title(chartname, va='bottom', fontproperties="simhei")
ax.set_rlim(0,10)
ax.grid(true)
plt.show()
2.2.10 深圳房屋外部指数量化雷达图模型
//todo 量化外部指标参数(学位,地铁距离,公交具体,公园分布,商圈等)
所以,还不会python的,想买房的,赶快来学习了!限时抢购哦!
下一篇: 微博抓取尝试