美文网首页
蘑菇租房爬虫数据分析

蘑菇租房爬虫数据分析

作者: 再见理想冷雨夜 | 来源:发表于2020-03-31 13:13 被阅读0次

    一、先上python代码

    #coding:utf-8
    
    import requests
    import random
    import json
    import datetime
    import pandas as pd
    import threading
    import time
    
    
    
    #创建多线程来执行任务
    def create_task(paramsList):
        threadList=[] #设置一个线程列表存储创建的线程
        print "一个有{}个参数".format(len(paramsList)) #打印出构建了多少个请求参数,有多少个参数就代表要执行多少次请求任务
        num=len(paramsList)/50  #每个线程执行50个任务,那需要多少个线程,50可以改变
        print '准备创建{}个线程'.format(num+1) #为防止漏掉任务,在上面结果上线程最好再+1
        for count in range(num+1): #for循环创建线程,同时要为每个线程分配不同的任务
            startParams = paramsList[::50][count] # 按50步长去切割参数列表,可以得到不同切割点的值
            startIndex=paramsList.index(startParams) #获取切割点的起始索引位置
            endIndex= startIndex + 50 #起始索引位置+50,为结束索引为准
            threadParamsList=paramsList[startIndex:endIndex] #根据起点和结束点,为参数列表分配不同任务
            print "已为一个线程分配好参数,有{}个参数".format(len(threadParamsList))
            thread=threading.Thread(target=get_data,args=(threadParamsList,)) #调用get_data方法,并为每个线程传入不同参数
            threadList.append(thread) #将线程添加到线程列表
        for thread in threadList:
            thread.setDaemon(True)  # 设置守护线程
            thread.start()  #开始线程
        for thread in threadList:
            thread.join() #所有子线程结束后再退出
    
    
    
    #城市ID和pageNum构建请求参数
    def create_params(cityIdList,pageNum):
        paramsList=[]
        for cityId in cityIdList:
            for num in range(1,pageNum+1):
                params={
                    'currentPage':num,
                    'cityId':cityId,
                    'showCount':18
                }
                paramsList.append(params)
        return paramsList
    
    #请求接口获取数据
    def get_data(threadParamsList):
        print "当前线程{}在执行任务...".format(threading.current_thread().name)
        #这里的list是用来存储每个线程爬取到的数据,存储完成后,再添加到全局变量list里
        cityIdList = []
        titleList = []
        detailDescList = []
        subTitleList = []
        locationList = []
        showPriceList = []
        labelsList = []
        latList = []
        lngList = []
        url='https://api.mgzf.com/room-find-web/find/list'
        for params in threadParamsList:
            randomTime=random.uniform(1,3) #随机的请求时间间隔,防止被封IP
            time.sleep(randomTime)
            res=requests.post(url,data=params,headers=headers)
            resDict=json.loads(res.text) #将json数据转化为dict类型
            resList=resDict['content']['list']
            labelDataList=[]
            for data in resList:
                #下面是根据返回的数据格式解析到自己想要的数据,这里具体场景具体分析
                cityIdList.append(data['cityId'])
                titleList.append(data['title'])
                detailDescList.append(data['detailDesc'])
                subTitleList.append(data['subTitle'])
                locationList.append(data['location'])
                showPriceList.append(data['showPrice'])
                for labelData in data['labels']: #label数据比较特殊,需要再一次for循环
                    labelDataList.append(labelData['title'])
                labelStr=','.join(labelDataList) #拼接获取到标签
                labelDataList=[] #请注意需要清空对应数据,否则拼接的数据会出错
                labelsList.append(labelStr)
                latList.append(data['lat'])
                lngList.append(data['lng'])
        #将每个爬虫获取到的数据添加到全局变量中,请注意这里要用extend,不用append,因为extend是追加列表数据
        cityId.extend(cityIdList)
        title.extend(titleList)
        detailDesc.extend(detailDescList)
        subTitle.extend(subTitleList)
        location.extend(locationList)
        showPrice.extend(showPriceList)
        labels.extend(labelsList)
        lat.extend(latList)
        lng.extend(lngList)
        print "当前线程{}执行任务完成".format(threading.current_thread().name)
    
    
    #存储数据
    def save_data():
        #由于接口返回数据没有城市名称,所以这边要比对所有cityId,从最初设置的cityData中拿到城市名称
           for id in cityId:
            for cityDict in cityData:
                if int(id)==cityDict['cityId']: #id类型需要由unicode转化为int
                    cityName.append(cityDict['name'])
    
        #构建一个字典,每个字段都是一个series,值是列表,方便把数据通过dateframe存储为表格形式
        data={
            'cityName':cityName,
            'cityId':cityId,
            'title':title,
            'detailDesc':detailDesc,
            'subTitle':subTitle,
            'location':location,
            'showPrice':showPrice,
            'labels':labels,
            'lat':lat,
            'lng':lng
        }
        print '开始存储数据,共有{}条数据'.format(len(data['cityId']))
        data=pd.DataFrame(data) #转化为datefram表格数据
        data.to_csv('../数据源/蘑菇租房数据.csv',encoding='utf-8-sig') #存储数据
        print "数据存储完成"
    
    
    
    
    if __name__=='__main__':
        startTime=time.time() #记录程序开始时间,后面用来计算爬虫耗时
        cityData=[
            {
                'name':'上海',
                'cityId':289
            },
            {
                'name': '成都',
                'cityId':75
            },
            {
                'name': '东莞',
                'cityId':119
            },
            {
                'name': '南京',
                'cityId':315
            },
            {
                'name': '合肥',
                'cityId':127
            },
            {
                'name': '北京',
                'cityId':131
            },
            {
                'name': '杭州',
                'cityId':179
            },
            {
                'name': '重庆',
                'cityId':132
            },
            {
                'name': '泉州',
                'cityId':134
            },
            {
                'name': '贵阳',
                'cityId':146
            },
            {
                'name': '长沙',
                'cityId':158
            },
            {
                'name': '宁波',
                'cityId':180
            },
            {
                'name': '厦门',
                'cityId':194
            },
            {
                'name': '武汉',
                'cityId': 218
            },
            {
                'name': '苏州',
                'cityId': 224
            },
            {
                'name': '西安',
                'cityId': 233
            },
            {
                'name': '广州',
                'cityId': 257
            },
            {
                'name': '郑州',
                'cityId': 268
            },
            {
                'name': '济南',
                'cityId': 288
            },
            {
                'name': '福州',
                'cityId': 300
            },
            {
                'name': '天津',
                'cityId': 332
            },
            {
                'name': '深圳',
                'cityId': 340
            }
    
        ] #通过浏览器审查元素可以得到每个城市的名称和城市ID,城市ID在后面请求接口的时候会用到
        idList=[]
        for city in cityData:
            idList.append(city['cityId']) #从cityData中把城市ID提取出来
        #通用的请求头设置,这里没啥好说的
        headers={
            'user-agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36',
            'refer':'http://www.mgzf.com/list/',
            'origin':'http://www.mgzf.com',
            'host':'api.mgzf.com',
            'Connection':'keep-alive',
            'Content-Type':'application/x-www-form-urlencoded'
        }
    
        #因为多线程去爬取数据,所以必须设置一个全局变量用来存储爬到的数据,因为各线程爬到的结果和速度都不一样
        cityId = []
        cityName=[]
        title = []
        detailDesc = []
        subTitle = []
        location = []
        showPrice = []
        labels = []
        lat = []
        lng = []
    
    
        page=raw_input("请输入爬取的页数:") #从页面上看,最大页数好像是30,所以输入30差不多
        pageNum=int(page) #输入的是str类型,需要转化为int
        paramsList=create_params(idList,pageNum) #调用构建请求参数方法
        create_task(paramsList) #调用创建多线程的方法
        save_data() #调用存储数据的方法
        endTime=time.time() #程序结束时时间
        print "爬虫结束,共耗时{}".format(endTime-startTime) #打印出整个爬虫的耗时
    

    二、爬取过程和结果


    image.png
    image.png

    三、利用tableau进行数据分析
    1、不同城市平均房租
    1)可以看到上海,杭州,北京的平均房租排名前,符合预期
    2)第一名的平均房租是最后一名郑州的几乎3倍价格,可以想象到一线城市的压力
    3)在下钻城市,拿上海举例,其中虹口区房租最贵高达5527,宝山和奉贤由于较为偏远,平均房租稍微便宜了点,而我住的普通平均房租是3515


    image.png
    image.png

    2、不同城市小区词云图
    1)筛选上海这座城市,可以看到九亭这边房源数比较多,属于松江区域
    2)图上颜色越深代表平均房租越贵,从大概位置上看以虹口徐汇地区为主


    image.png

    3、不同城市户型分析
    1)筛选了一线城市(上海北京杭州)的户型,可以看到以一室一厅一卫为主,说明市场需求以这种一室一厅的整租为主,从价格上3000元也在可接收范围内
    2)再看看二三线城市的分布(宁波郑州等),可以看出,户型出租以多居室为住,平均单间价格为900
    3)从这2个图可以看出,一二线城市的出租类型差异化还是很大的


    image.png
    image.png
    4、不同城市房子描述分析
    1)对于一线城市(比如上海),地铁,中心地段,为主要描述关键词

    相关文章

      网友评论

          本文标题:蘑菇租房爬虫数据分析

          本文链接:https://www.haomeiwen.com/subject/syfwuhtx.html