0 簡(jiǎn)介
今天學(xué)長(zhǎng)向大家介紹一個(gè)適合作為畢設(shè)的項(xiàng)目
畢設(shè)分享 python大數(shù)據(jù)房?jī)r(jià)預(yù)測(cè)與可視化系統(tǒng)
項(xiàng)目獲?。?/strong>
https://gitee.com/sinonfin/algorithm-sharing文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-755720.html
1 數(shù)據(jù)爬取
1.需求描述
對(duì)于數(shù)據(jù)挖掘工程師來(lái)說(shuō),有時(shí)候需要抓取地理位置信息,比如統(tǒng)計(jì)房子周邊基礎(chǔ)設(shè)施信息,比如醫(yī)院、公交車站、寫字樓、地鐵站、商場(chǎng)等,一般的爬蟲可以采用python腳本爬取,有很多成型的框架如scrapy,但是想要爬百度地圖就必須遵循它的JavaScriptApi,那么肯定需要自己寫JavaScript腳本與百度API進(jìn)行交互,問(wèn)題是:這種交互下來(lái)的數(shù)據(jù)如何儲(chǔ)存(直接寫進(jìn)文本or使用sql數(shù)據(jù)庫(kù)?),如何自動(dòng)化這種交互方式。
因此,本文的目標(biāo)是用一個(gè)rails應(yīng)用配合js腳本來(lái)實(shí)現(xiàn)這種自動(dòng)化抓取和儲(chǔ)存,思路是js腳本負(fù)責(zé)與百度地圖Api交互,rails服務(wù)器端負(fù)責(zé)儲(chǔ)存抓取的數(shù)據(jù),js和rails服務(wù)器用ajax方式傳遞數(shù)據(jù).前提是rails服務(wù)器里已經(jīng)有相應(yīng)的房屋數(shù)據(jù),如房屋的街道地址,小區(qū)名字等. 接下來(lái)需要做的就是為周邊信息數(shù)據(jù)建表以及相應(yīng)的關(guān)聯(lián)表(因?yàn)樗鼈優(yōu)槎鄬?duì)多關(guān)系)
2.流程詳解
js代碼在用戶瀏覽器中執(zhí)行,因此爬取的主要部分邏輯都需要寫在js腳本里,而rails服務(wù)器端需要完成的是獲得當(dāng)前需要抓取的房屋數(shù)據(jù)以及儲(chǔ)存js抓取的數(shù)據(jù)。下圖為對(duì)id=1的房屋周邊數(shù)據(jù)抓取的分解過(guò)程:
-
- 首先由用戶在瀏覽器中點(diǎn)擊開始按鈕,激活GetDataFromServer()方法,瀏覽器向rails服務(wù)器發(fā)送請(qǐng)求,服務(wù)器的return_next()方法返回當(dāng)前需要抓取的房屋數(shù)據(jù)(主要是街道或者小區(qū)的位置信息)
-
- 通過(guò)getPoint方法,瀏覽器向Baidu API 發(fā)送請(qǐng)求查找房屋坐標(biāo),若有結(jié)果則繼續(xù),否則直接遞歸調(diào)用GetDataFromServer()
-
- 使用查詢到的房屋坐標(biāo)搜索周邊的信息:對(duì)于每一類信息(如地鐵,醫(yī)院等),在查詢到結(jié)果后立即向服務(wù)器發(fā)送查詢結(jié)果以及房屋信息,并標(biāo)記當(dāng)前的數(shù)據(jù)類型(地鐵,醫(yī)院…).服務(wù)器在接收到數(shù)據(jù)后,先判斷數(shù)據(jù)類型,然后根據(jù)類別再對(duì)房屋的周邊信息進(jìn)行儲(chǔ)存.
-
- 如果完成當(dāng)前房屋所有的周邊數(shù)據(jù)的查詢后, 再次調(diào)用GetDataFromServer()來(lái)獲得下一個(gè)房屋的數(shù)據(jù)
3. 代碼實(shí)現(xiàn)
3.1 瀏覽器端(js)
1.GetDataFromServer
: ajax向get_data_url地址以get方法請(qǐng)求json格式的數(shù)據(jù),成功拿到數(shù)據(jù)后先用小區(qū)來(lái)匹配房屋坐標(biāo),如果失敗再用街道匹配,若兩者都沒(méi)找到結(jié)果,那么此房屋的地理信息為空,則查詢下一個(gè)房屋;若能找到房屋坐標(biāo),調(diào)用SearchStart()開始搜索周邊數(shù)據(jù)
?
function GetDataFromServer() {
$.ajax({
type: "GET",
url: get_data_url,
dataType: 'json',
success: function (house_data) {
// 拿到房屋數(shù)據(jù)后先顯示出來(lái)
displayHouseData(house_data);
// 然后先用街道去查坐標(biāo)
myGeo.getPoint(house_data.street, function (point) {
if (point) {
// 如果查到坐標(biāo),開始檢索周圍信息
SearchStart(point, house_data);
} else {
// 如果
2.SearchStart
和SearchNearby
: SearchStart為SearchNearby的入口,SearchNearby方法構(gòu)建了一個(gè)BMap.LocalSearch對(duì)象的函數(shù)變量,調(diào)用searchNearby并傳入關(guān)鍵詞就可以查找house_loc附近的所有的包含關(guān)鍵詞的位置信息,search_range能指定查找附近的范圍.
BMap.LocalSearch通過(guò)onSearchComplete指定了查詢完成后的回調(diào)函數(shù):這里我們對(duì)查詢的結(jié)果做一個(gè)遍歷,計(jì)算出這個(gè)查詢結(jié)果與房屋的距離,然后將這些信息整合到一個(gè)數(shù)組里,傳給sendData()來(lái)發(fā)送數(shù)據(jù)
?
function SearchStart(point, house_data) {
// 先在地圖上標(biāo)記出來(lái)
map.centerAndZoom(point, 16);
map.addOverlay(new BMap.Marker(point));
// 首先查詢此房屋的第一個(gè)關(guān)鍵詞信息(公交車站,idx=0)
setTimeout(function () {
SearchNearby(point, house_data, 0);
}, timeInterval);
}
function SearchNearby(house_loc, house_data, keyword_idx) {
var nearby_info = [];
// 清除地圖覆蓋物
map.clearOverlays();
var local = new BMap.LocalSearch(map, {
renderOptions: {map: map, autoViewport: false},
pageCapacity: 50,
onSearchComplete: function (results) {
DisplayClear();
if (local.getStatus() == BMAP_STATUS_SUCCESS) {
// 百度地圖成功返回,將每個(gè)周邊信息儲(chǔ)存到nearby_info里
for (var i = 0; i < results.getCurrentNumPois(); i++) {
var locate = results.getPoi(i);
if (locate != null) {
// 查詢結(jié)果與房屋的距離
var distance = parseFloat(map.getDistance(locate.point, house_loc)).toFixed(1);
nearby_info.push(locate.title + "/" + locate.point.lng + '/' + locate.point.lat + '/' + distance);
DisplayNearbyData(nearby_info, locate, distance)
}
}
// 獲得百度地圖查詢結(jié)果后立即發(fā)送給服務(wù)器
return sendData(keywords_en[keyword_idx], nearby_info, house_data, house_loc, keyword_idx)
} else {
GetDataFromServer();
console.log("No records with baiduAPI:", local.getStatus());
return false;
}
}
});
local.searchNearby(keywords[keyword_idx], house_loc, search_range);
}
3.sendData
: sendData負(fù)責(zé)發(fā)送查詢數(shù)據(jù)nearby_info,周邊數(shù)據(jù)類型由nearby_type指定,房子本身的數(shù)據(jù)信息由house_data提供而坐標(biāo)由house_loc給出, idx記錄著現(xiàn)在查詢的關(guān)鍵詞的索引.
sendData使用ajax post方法提交數(shù)據(jù), 當(dāng)提交成功后,通過(guò)調(diào)用SearchNearby并傳遞下一個(gè)關(guān)鍵詞的id來(lái)檢索這個(gè)房子其他周邊信息;如果當(dāng)前關(guān)鍵詞已經(jīng)是最后一個(gè),那么調(diào)用GetDataFromServer來(lái)啟動(dòng)下一輪的查詢
?
function sendData(nearby_type, nearby_info, house_data, house_loc, idx) {
data = "nearby_type=" + nearby_type + "&nearby;_info=" + nearby_info + "&id;=" + house_data.id + "?=" + house_loc.lat + "&lng;=" + house_loc.lng;
$.ajax({
type: "POST",
url: post_data_url,
data: data,
dataType: "JSON",
success: function (data) {
if (flag) {
console.log("warning", 'pause');
} else {
// 當(dāng)查詢到最后一個(gè)kewords時(shí),請(qǐng)求服務(wù)器獲得下一個(gè)房屋信息
if (idx == keywords.length - 1) {
GetDataFromServer();
} else {
// 查詢此房屋的下一個(gè)關(guān)鍵詞信息
setTimeout(function () {
SearchNearby(house_loc, house_data, idx + 1);
}, timeInterval);
}
console.log("success", data);
}
return true;
},
error: function () {
alert('error in post');
return false;
},
timeout: function () {
alert('time out in post');
return false;
}
});
}
2 設(shè)計(jì)內(nèi)容
2.1. 數(shù)據(jù)挖掘 (Done)
1.1 在房?jī)r(jià)網(wǎng)站上利用爬蟲爬下當(dāng)前所有房子的價(jià)格和基本信息(房型、面積、樓層、建造時(shí)間等)
1.2 利用百度API對(duì)每套房產(chǎn)的周邊信息進(jìn)行挖掘(公交車站、地鐵、寫字樓、醫(yī)院、學(xué)校、商場(chǎng)等)
1.3 將所有信息儲(chǔ)存在關(guān)系型數(shù)據(jù)里,構(gòu)建數(shù)據(jù)倉(cāng)庫(kù)(Data Warehouse)
2.2. 建立模型對(duì)數(shù)據(jù)進(jìn)行分析(Under Construction)
2.1 選擇模型
2.2 訓(xùn)練
2.3. 數(shù)據(jù)可視化(Partial done)
3.1 導(dǎo)入百度的可視化工具庫(kù)(Echarts)
3.2 利用訓(xùn)練的模型對(duì)指定房屋價(jià)格進(jìn)行評(píng)估和預(yù)測(cè),并以科學(xué)地方法將結(jié)果進(jìn)行可視化展示
房屋預(yù)測(cè)功能具體應(yīng)用場(chǎng)景:
-
對(duì)于買家,輸入那個(gè)房子的坐標(biāo),我們通過(guò)這個(gè)數(shù)據(jù)集對(duì)這個(gè)房子的價(jià)錢進(jìn)行預(yù)測(cè),以幫助買家合理判斷值不值買這個(gè)房子(開發(fā)中)
-
對(duì)于賣家,輸入他自己的房子坐標(biāo),我們可以對(duì)這個(gè)房子價(jià)錢進(jìn)行評(píng)估,讓賣家對(duì)自己的賣價(jià)有個(gè)大致的定位,更好的選擇自己的出手價(jià)格(開發(fā)中)
設(shè)計(jì)效果截圖
數(shù)據(jù)說(shuō)明
現(xiàn)有的一些字段以及字段之間的關(guān)聯(lián)如下:
data_type.png
7.開發(fā)
原始數(shù)據(jù)由[scrapy-hoursepricing]爬取,抓取后的數(shù)據(jù)將存為json格式,然后由HousePricing進(jìn)行解析并儲(chǔ)存在數(shù)據(jù)庫(kù)中
本項(xiàng)目由rails框架開發(fā),請(qǐng)自行安裝相關(guān)環(huán)境,請(qǐng)先f(wàn)ork此項(xiàng)目,然后運(yùn)行下面:
git clone your_forked_project
cd project_path
bundle install
rake db:migrate
rake db:seed
在瀏覽器中輸入localhost:3000
,即可訪問(wèn)主頁(yè)
8.Docker運(yùn)行
為了方便運(yùn)行和部署,這里提供了簡(jiǎn)單的docker鏡像。
開發(fā)者首先需要在電腦上安裝docker
和docker-compose
,然后運(yùn)行下面:
# 編輯數(shù)據(jù)庫(kù)配置
cp docker-util/app.env.example docker-util/app.env
vim docker-util/app.env
# 拉取或生成鏡像
docker-compose build
# OR
docker pull pengedy/housepricing
# 運(yùn)行
docker-compose up
即可訪問(wèn)http://localhost:3000
若需要原數(shù)據(jù)(我目前用的數(shù)據(jù)),請(qǐng)導(dǎo)入根目錄下的mydb.dump
到postgresql數(shù)據(jù)庫(kù)
最后
項(xiàng)目分享:文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-755720.html
https://gitee.com/sinonfin/algorithm-sharing
到了這里,關(guān)于畢設(shè)分享 python大數(shù)據(jù)房?jī)r(jià)預(yù)測(cè)與可視化系統(tǒng)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!