日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

房价在手,天下我有 --反手就撸一个爬虫(终)

發布時間:2023/12/2 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 房价在手,天下我有 --反手就撸一个爬虫(终) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

接上篇,科科,好,我們繼續

我們在這里先把json數據入庫吧~

首先,database/scheme里定義好數據類型。

const mongoose = require('mongoose')const detailHouseSchema = new mongoose.Schema({ //定義數據模式link:String,text:String,_id:String,areaDetail:[{link: String,text: String,_id: String,house:[{name: String,huxing: String,favorPos: String,aroundPrice: Number,adress: String,area:?String?}]}] })mongoose.model('detailHouse',detailHouseSchema)

然后我們需要到中間件里去建立連接數據庫和執行插入的動作。

middleWares/database.js

import mongoose from 'mongoose' import config from '../config' import fs from 'fs' import { resolve } from 'path'const r = path => resolve(__dirname,path) //將路徑片段轉成一個絕對路徑 const models = r('../database/schema') /*** 依次引入本地爬去好的json文件,插入數據庫*/ var areaJson = require('database/json/AreaDetail.json') var areaHouseJson = require('database/json/AreaHouse.json') var detailHouseJson = require('database/json/detailHouse.json')/*** 依次引入schema*/ fs.readdirSync(models) //讀取文件.filter(file => ~file.search(/^[^\.].*js$/)) //篩選出后綴是js的文件.forEach(file => require(resolve(models,file))) export const database = app =>{mongoose.set('debug',true)mongoose.connect(config.db)mongoose.connection.on('disconnected', ()=>{mongoose.connect(config.db)})mongoose.connection.on('error', err =>{console.log(err)})mongoose.connection.on('open', async () =>{console.log('connected to MongoDb',config.db)/*** 杭州主城區數據入庫*/let area = mongoose.model('area')let areaDataBase = await area.find({}).exec()if (!areaDataBase.length) area.insertMany(areaJson)/*** 杭州主城區的房價數據入庫*/let areaHouse = mongoose.model('areaHouse')let areaHouseDataBase = await areaHouse.find({}).exec()if(!areaHouseDataBase.length) areaHouse.insertMany(areaHouseJson)/*** 杭州主城區里包括了分區的房價數據入庫*/let detailHouse = mongoose.model('detailHouse')let detailHouseDataBase = await detailHouse.find({}).exec()if(!detailHouseDataBase.length) detailHouse.insertMany(detailHouseJson)}) }

成功的話,如下圖~ bling~~~

走到這里,我們要停下來對后端的路由做一個提取個封裝。首先,我這項目頁面量不大,如果單純的用koa-router去原生去寫是沒有問題的,但是如果你是實際的項目,路由很多,這個時候再去那么寫,代碼的可讀性就很差了。

Decorator可以動態地給一個對象添加額外的職責。雖然,利用子類繼承也可以實現這樣的功能,但是Decorator提供了一個更靈活的方式。因為繼承會為類型引入的靜態特質,使得這種擴展方式缺乏靈活性;并且隨著子類的增多(擴展功能的增多),各種子類的組合(擴展功能的組合)會導致更多子類的膨脹。

那么我們要在decorator/router.js里要定義一些公用的方法,其中還添加了打印日志功能,在調試的時候也是美滋滋的一匹。

先去middlewares/routers/router.js里去調用我們用修飾起封裝好的方法和Route。

import Route from '../decorator/router' import { resolve } from 'path'const r = path => resolve(__dirname, path)export const router = app => {const apiPath = r('../routes')/*** 路由分離*/const router = new Route(app, apiPath)router.init() }

現在去封裝Route

decorator/router.js

import Router from 'koa-router' import { resolve } from 'path' import _ from 'lodash' import { glob } from 'glob' //用正則去匹配文件export let routesMap = new Map() export const symbolPrefix = Symbol('prefix') export const normalizePath = path => path.startsWith('/') ? path : `/${path}` export const isArray = c => _.isArray(c) ? c : [c]export default class Route{constructor(app,apipath){this.app = appthis.router = new Router()this.apipath = apipath}init(){/*** 這里利用傳進來的apipath去引入后綴為js的文件*/glob.sync(resolve(this.apipath,'./*.js')).forEach(require);for(let [ conf , controller ] of routesMap){/**思路就是把每一個路由文件的controller拎出來* 然后跟它的路由做一個一一匹配* */const controllers = isArray(controller) let prefixPath = conf.target[symbolPrefix]if(prefixPath) prefixPath = normalizePath(prefixPath)const routerPath = prefixPath conf.paththis.router[conf.method](routerPath,...controllers) //function (name, path, middlewares)}this.app.use(this.router.routes()) // 添加路由中間件this.app.use(this.router.allowedMethods()) // 對請求進行一些限制處理} }/*** * @param {path,target} * 保證每一個controller都是獨一無二的 */ export const controller = path => target => target.prototype[symbolPrefix] = path/*** * @param {conf} * 定義簡單的route */ export const route = conf => (target, key, desc) =>{conf.path = normalizePath(conf.path)routesMap.set({target:target,...conf,},target[key]) }/*** * @param {path} * 定義get方法*/ export const get = path => route({method:'get',path:path })/*** * @param {path} * 定義post方法 */ export const post = path => route({method:'post',path:path })/*** * 打印日志*/ let reqID = 0const decorate = (args, middleware) => {let [ target, key, descriptor ] = argstarget[key] = isArray(target[key])target[key].unshift(middleware)return descriptor }export const convert = middleware => (...args) => decorate(args, middleware)export const log = convert(async (ctx, next) => {let currentReqID = reqID console.time(`${currentReqID} ${ctx.method} ${ctx.url}`)await next()console.timeEnd(`${currentReqID} ${ctx.method} ${ctx.url}`)})

然后再來看看我們接口定義的文件,代碼趕緊簡潔的一匹.

routes/crawler.js

import { controller, get , log} from '../decorator/router' import mongoose from 'mongoose'const areaDataBase = mongoose.model('area') const areaHouseDataBase = mongoose.model('areaHouse') const detailHouse = mongoose.model('detailHouse')@controller('') export class Crawler{/*** 獲取杭州城區下的房子信息*/@get('/getDetail')@logasync detailHouse (ctx,next){let query = ctx.querylet { _id } = query;if (!_id) return (ctx.body = '_id is required')let area = await detailHouse.findById(_id).exec()ctx.body = {code:0,area}} /*** 獲取杭州城區下的房子信息*/@get('/getAreaHouse')@logasync areaHouse (ctx,next){let areaHouse = await areaHouseDataBase.find({}).exec()ctx.body = {code:0,areaHouse}} /*** 獲取杭州城區單條的名稱*/@get('/getArea/:_id')@logasync getArea (ctx,next){const { params } = ctxconst { _id } = paramsif (!_id) return (ctx.body = '_id is required')let area = await areaDataBase.findById(_id).exec()ctx.body = area} /*** 獲取杭州城區的名稱*/@get('/getArea')@logasync Area (ctx,next){let area = await areaDataBase.find({}).exec()ctx.body = {code:0,area}}}

走到這里,后端的代碼基本上全部完成了,我們從數據的爬取-->入數據庫-->-->接口的定義。

剩下的就是簡單的前端的接口調用啦~ 我這里就不具體展示出代碼啦~接口調用完成,基本上就能完成我們的目標樣子啦~

真心的話要放在最后,這是小弟第一次從后到前擼的項目,對于node,mongo,數據庫如何建表研究的還很膚淺,小弟在這里班門弄斧啦~真心希望和我一樣喜歡倒騰的小伙伴可以自己也上手玩玩~真的能學到不少知識~

本來還想放上源碼的,礙于注釋都沒有添加的很全,容老夫慢慢把注釋不全了在貼出來~


2018/07/31

源碼地址

總結

以上是生活随笔為你收集整理的房价在手,天下我有 --反手就撸一个爬虫(终)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。