数据爬取

本篇博客所讲为数据爬取,及处理。

  • 爬取基本数据
  • 对数据进行处理
  • 将数据量化,即数字化
  • 利用机器学习模型做出预测

→贝壳租房网西安
我们需要从这里爬取数据,理由是相较于其他租房网站来说,该网站反爬没有那么严格,虽然前一段时间好像加强了反爬但是,还是突破还是比较轻松的。
这里我们需要的关键信息为

header=['房源编号', '所在城市', '区县', '所在街道', '小区名称', '面积', '租赁方式', '朝向', '月租', '计费', '室', '厅', '卫', '入住', '租期', '看房', '所在楼层', '总楼层', '电梯', '车位', '用水', '用电', '燃气', '采暖']

我们以爬取五十页的数据并存入csv文件或者excel文件中,存入什么文件不是特别重要我们最后需要的是一个dataframe结构,也就是机器学习需要的结构,同时后面我们会将该结构转化为numpy.array。
先上代码:

#kaggle 房价预测一:爬取信息
#两个模块用于处理信息
import csv
import re
#该模块用于爬取信息
from bs4 import BeautifulSoup
import requests
import time
#csv文件的标题行
header=['房源编号', '所在城市', '区县', '所在街道', '小区名称', '面积', '租赁方式', '朝向', '月租', '计费', '室', '厅','卫', '入住', '租期', '看房', '所在楼层', '总楼层', '电梯', '车位', '用水', '用电', '燃气', '采暖']
#获得头部信息
headers={'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:79.0) Gecko/20100101 Firefox/79.0'}
with open("E:\\桌面\\kaggle房价预测.csv","w",newline="") as filewrite:
#创建写入对象filewriter=csv.writer(filewrite)
#写入标题行filewriter.writerow(header)
#https://xa.zu.ke.com/zufang/pg2/#contentList ←第二页的网址  https://xa.zu.ke.com/zufang ←第一页的网址 这里可以看出来规律  for page in range(1,51):
#url的规则url='https://xa.zu.ke.com/zufang/pg'+str(page)+'/#contentList'
#获得responseresponse=requests.get(url=url,headers=headers)
#验证网页是否请求正常        if response.status_code==200 :passelse:print("该网页:"+str(url)+"未请求成功!")continue
#获得 .text 属性page_text = response.text
#利用BeautifulSoup的html.parser对属性进行解析 soup=BeautifulSoup(page_text,"html.parser")div_list=soup.find_all(class_='content__list--item')
#房源编号 更新codescodes=[]for div in div_list:code=re.search(r'data-house_code="(.*?)" ', str(div)).group()[17:-2]codes.append(code)
#储存地区areas=[]p_list=soup.find_all(class_="content__list--item--des")for p in p_list:area=[]a_list=p.find_all('a')for a in a_list:a_text=a.textif a_text==' ' or a_text=='':a_text="暂无"area.append(a_text)areas.append(area)for i in range(len(codes)):time.sleep(1)
#更新message        message=[]message.extend([codes[i],'西安']+areas[i])
#利用code去进入每个详细页面的url 如:https://xa.zu.ke.com/zufang/XA2565970386130829312.html?nav=0&unique_id=ccca3468-0ef2-43fc-8ea0-0a41b42e0720zufangpg21598277997500url='https://xa.zu.ke.com/zufang/'+str(codes[i])+'.html'
#获得page_textpage_text=requests.get(url=url,headers=headers).textsoup=BeautifulSoup(page_text,'html.parser')try:ul_text=soup.find('ul',class_="content__aside__list").textexcept:print(message[0]+"该页面进入失败!请检查!")continue
#这里对正则的基本功有一定要求,比如,这里我们匹配面积的时候要注意 是在空格和㎡之间,因此空格不能少,以下的\n同理。
#同时我们要使用group截断我们匹配到的字符串防止其他莫名的信息
#获得面积s=re.search(r' (.*?)㎡',ul_text).group()[1:]
#租赁方式lease=re.search(r'租赁方式:(.*?)\n',ul_text).group()[5:-1]
#朝向aspect = re.search(r'朝向楼层:(.*?) ', ul_text).group()[5:-1]
#这里我是按照需要的信息顺序匹配
#月租 div_text=soup.find('div',class_="content__aside--title").textmonthly_rent=re.search(r'([0-9]*?)元/月',div_text).group()[:-3]
#计费方式try:charge_way=re.search(r'\((.*?)\)',div_text).group()[1:-1]except:charge_way="暂无"
#几室几厅几卫rooms=re.search(r'([0-9]*?)室',ul_text).group()[:-1]halls=re.search(r'([0-9*?])厅', ul_text).group()[:-1]toilets=re.search(r'([0-9*?])卫', ul_text).group()[:-1]
#其他信息            div_text=soup.find('div',class_='content__article__info').text
#入住check_in=re.search(r'入住:(.*?)\n', div_text).group()[3:-1]
#租期lease_day=re.search(r'租期:(.*?)\n',div_text).group()[3:-1]
#看房see_room=re.search(r'看房:(.*?)\n',div_text).group()[3:-1]
#所在楼层in_floor=re.search(r'楼层:(.*?)/',div_text).group()[3:-1]
#总楼层all_floors=re.search(r'/(.*?)\n',div_text).group()[1:-1]
#电梯elevator=re.search(r'电梯:(.*?)\n',div_text).group()[3:-1]
#车位stall = re.search(r'车位:(.*?)\n', div_text).group()[3:-1]
#用水water=re.search(r'用水:(.*?)\n',div_text).group()[3:-1]
#用电elect=re.search(r'用电:(.*?)\n',div_text).group()[3:-1]
#燃气gas=re.search(r'燃气:(.*?)\n',div_text).group()[3:-1]
#采暖heating=re.search(r'采暖:(.*?)\n',div_text).group()[3:-1]
#填入messagemessage.extend([s,lease,aspect,monthly_rent,charge_way,rooms,halls,toilets,check_in,lease_day,see_room,in_floor,all_floors,elevator,stall,water,elect,gas,heating])
#检查数据           try:filewriter.writerow(message)except:print(message[0]+"写入失败,请检查!")continue

由于我们需要的信息在架构中的位置各有不同,因此代码会显得冗杂,我尽量让它显得赏心悦目吧。
我们来看一下爬取信息的大概位置。

该页面完整的捕捉到这些信息之后,我们进入详细页面获得详细的信息。注意这里每个详细页面的网址有固定的格式为:
https://xa.zu.ke.com/zufang/+str(codes[i])+.html
这也是我们为什么首先要爬取房源编号,并存入一个列表的原因,这样做有利于我们访问每个详细页面。
这里是租价,及交付方式。

这里是面积,朝向等详细信息,对应页面的这里

代码修改前遇到的问题:

  1. 出现了需要人机验证的问题,这说明你快速的访问触及了人的反爬机制。最好的处理方法是每一个页面的访问底下加一个time.sleep()该方法已经帮我避过了很多次反爬。
  2. 部分数据错误导致无法截取,这个问题,我用try except处理掉了一两条,大部分都不会有什么问题,这类问题应该是前端工程师的锅。
  3. 该代码目前在西安租房这块是没有问题的,但是html他不是静态不变的,可能更新某个数据之后会出现问题,但是稍微去修改就可以了。

数据处理:

爬取数据之后,他还存在一些比较无用的单位,比如房租后面的单位,或者说楼层后面的单位,还有在楼层位置那块我们只需要三个数字表示高低中楼层就可以了,不需要那些多少楼的数据
,这些数据都需要处理,因此我们进行信息处理。
代码:

#kaggle房价预测二:处理信息
import csv
import re
flag_list=["高楼层","中楼层",'低楼层']
with open("E:\\桌面\\kaggle房价预测.csv",'r',newline='') as fileread:with open('E:\\桌面\\数据数据化一.csv','w',newline='') as filewrite:
#创建读取对象 及 写入对象filereader=csv.reader(fileread)filewriter=csv.writer(filewrite)
#略过第一行header=next(filereader)
#写入头部filewriter.writerow(header)for row_list in filereader:
#去掉㎡row_list[5]=row_list[5][:-1]
#朝向去掉后面的保留第一个 原先的朝向若有两者以上 以/隔开row_list[7]=row_list[7].split('/')[0]
#入住时间处理  利用空行替换/row_list[13]=row_list[13].replace('-','')
#先处理总层数row_list[17]=row_list[17].replace('层','')
#对所在楼层处理为 低中高楼层if row_list[16]=='地下室':row_list[16]='低楼层'elif row_list[16] not in flag_list :if int(row_list[16]) <= int(row_list[17])/3:row_list[16]=flag_list[2]elif int(row_list[17]) / 3 < int(row_list[16]) < int(row_list[17]) / 3 * 2:row_list[16]=flag_list[1]else:row_list[16]=flag_list[0]
#利用pop删除索引0 也就是房源编号row_list.pop(0)filewriter.writerow(row_list)
#第一步处理完成

这里处理完成后,大概不会有什么问题,我们将数据数字化。

#kaggle房价预测二:信息数据化
#这里对对应地区进行编号,因为我们需要的机器学习模型是不能识别字符串的。
import csv
import re
#为了地区的编号可以设置一个编号函数实现自动编号 三个地区需要编号,我们需要设置三个列表和三个整数完成函数的使用
def Automatic_numbering(element,label_list,label):'''举例 假设我们填入的三个地区为 a b a那么a先进去 ,设置label初始值为1第一返回1 2 这是label为2再进去b 这时返回2 3,label为3 在填入a 这是返回1 3 label依然为3,因为a与a重名不需要重新赋值'''if element not in label_list:label_list.append(element)ret=labellabel+=1else:ret = label_list.index(element) + 1return ret,label
#设置初始的三个列表和整数
label_list_a,label_list_b,label_list_c=[],[],[]
label_a=label_b=label_c=1
#这里的all_days得用在后面处理特殊情况
all_days=0
all_rows=[]
with open("E:\\桌面\\数据数据化一.csv",'r',newline="") as fileread:with open("E:\\桌面\\数据编码二.csv",'w',newline="") as filewrite:
#创建读写对象filereader=csv.reader(fileread)filewriter=csv.writer(filewrite)header=next(filereader)
#将头部写入filewriter.writerow(header)for row_list in filereader:
#这里我利用西安的数据 西安的编码记为3row_list[0]=3
#对区县位的编码row_list[1],label_a=Automatic_numbering(row_list[1], label_list_a, label_a)row_list[2],label_b=Automatic_numbering(row_list[2], label_list_b, label_b)row_list[3],label_c=Automatic_numbering(row_list[3], label_list_c, label_c)
#对租赁方式 整租为 1 合租为 2if row_list[5]=='整租':row_list[5]=1else:row_list[5]=2
#需要一个总的字典,包含各种编码all_dic={'东': 1, '南': 2, '西': 3, '北': 4, '东南': 5, '东北': 6, '西南': 7, '西北': 8,'未知':0,'月付价': 1, '季付价': 2, '半年付价': 3, '年付价': 4,'双月付价':5,'None': 0,'暂无':0,'随时入住': 1,'随时可看': 1, '需提前预约': 2, '一般下班后可看': 3,'只能周末看房':4,'低楼层': 1, '中楼层': 2, '高楼层': 3,'有': 1, '无': 2, '暂无数据': 3,'暂无数据': 1, '免费使用': 2, '租用车位': 3,'民水': 1, '商水': 2, '暂无数据': 3,'民电': 1, '商电': 2, '暂无数据': 3,'有': 1, '无': 2, '暂无数据': 3,'集中供暖': 1, '自采暖': 2, '暂无数据': 3}
#对朝向的编码 row_list[6]=all_dic[row_list[6]]
#计费方式 row_list[8]=all_dic[row_list[8]]
#入住if row_list[12]=="随时入住":row_list[12]=1elif row_list[12]=='暂无数据':row_list[12]=0
#租期 利用sub函数将无用项全部替换为空格。用split分开,这个思路应该是我前一段时间看到我一个朋友的代码是这么写的,觉得挺好,借鉴的if row_list[13] != '暂无数据':if re.search(r'年', row_list[13]):day= int(re.sub(r'(\D)', ' ', row_list[13]).split()[0])*12elif re.search(r'月', row_list[13]):day= int(re.sub(r'(\D)', ' ', row_list[13]).split()[0])row_list[13]=dayall_days+=day
#看房row_list[14]=all_dic[row_list[14]]
#所在楼层            row_list[15]=all_dic[row_list[15]]
#电梯row_list[17]=all_dic[row_list[17]]
#车位row_list[18]=all_dic[row_list[18]]
#用水row_list[19]=all_dic[row_list[19]]
#用电row_list[20]=all_dic[row_list[20]]
#燃气row_list[21]=all_dic[row_list[21]]
#采暖row_list[22]=all_dic[row_list[22]]all_rows.append(row_list)for row in all_rows:if row[13]=='暂无数据':row[13]=all_days//1503filewriter.writerow(row)

对信息数据化。

  1. 地区,小区名等等,我们需要对它进行编号,而我们是不可能手动编号的,因此我们用一个自动编号的函数,函数的原理在代码中已经详解,很容易理解。
  2. 对于部分缺失的数据,我们利用众数或者平均数替代,使误差最小化。
  3. 提前设置一个大的字典,对应各个字符串,这是我能想到最方便的方法,每一次赋值访问字符串便可。
  4. 租期我们按最小租期去算。

1.
代码仅用于对西安租房数据的爬取及处理,若是换做其他城市可能多多少少会有一些报错,不过没关心,应该都只是小问题,我们最后处理出来的数据一定要是纯数字,否则我们需要的机器学习模型无法运行。
2.
预测房价需要大量的数据,因此不能仅靠一个城市的租房数据去判断,可以改代码去爬取成都,天津等等地方的数据,整合之后利用机器学习模型去预测会更加准确,甚至可以准确到契合度为百分之九十九点九,数据就是这么可怕。

这边我放一个模型吧,不太想详解,可以的话,放到下一篇博客吧。

#放入机器学习模型
import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split
#k邻近模型
from sklearn.neighbors import KNeighborsRegressor
#加载数据
data=pd.read_csv('E:\\桌面\\数据编码二.csv', encoding='gb18030')
#利用train_test_split分离测试集与数据集 这里注意drop函数返回一个已经取消了列的dataframe
X_train,X_test,y_train,y_test = train_test_split(np.array(data.drop(columns=['月租'])), np.array(data['月租']),test_size=0.2, random_state=22)
#构建模型
knn_mode=KNeighborsRegressor(n_neighbors=5)
knn_mode.fit(X_train,y_train)
y_predict= knn_mode.predict(X_test)
print(y_predict)
print('the score is {0:.2f}'.format(knn_mode.score(X_train, y_train)))

<机器学习 房价预测 >对贝壳租房网 信息爬取 及处理。相关推荐

  1. 中国土地市场网信息爬取--requests+Selenium多线程爬取

    这次爬取的网站是中国土地市场信息网站https://www.landchina.com/default.aspx?tabid=263 先进行观察分析这个.发现这个网站以下有几个特点: 1.网站响应速度 ...

  2. 实战-selenium实现BOSS直聘网信息爬取

    实现了monodb和csv的文件写入 mongodb如下: 这里学历要求获取错了,取错列表下标了...,代码已经改正 Excel如下: 这里学历要求获取错了,取错列表下标了...,代码已经改正 待解决 ...

  3. python网易云热歌榜歌曲信息爬取(iframe框架内数据爬取,src为空)

    为一线医护人员加油! 为武汉加油! 为中国加油! 为世界加油! 此爬虫是本人参考了了一位前辈的文章,并修改和优化了代码: 1.改为python3环境: 2.优化了抓取的歌曲时长中带一长串小数的问题: ...

  4. 基于scrapy下的租房信息爬取与数据展示工具的设计与实现

    环境:python 3.6.0 Anaconda custom 64bit 4.3.0 Pycharm x64 专业版 2018.1.2 Web strom x64 专业版 2018.1.3 scra ...

  5. 网易云音乐歌手歌曲、用户评论、用户信息爬取

    这里以邓紫棋歌手为例,可以去网易云音乐看她的主页: 所有完整的代码在楼主的github:https://github.com/duchp/python-all/tree/master/web-craw ...

  6. 生成osm文件_超酷城市肌理!地理数据信息爬取方法大全(B篇)DEM+POI+OSM

    WENWEN:这一弹是对第一弹的补充和深化讲解,上一弹请点击常用的地理数据信息爬取方法大全(前期场地信息获取第一弹),关于DEM获取地形地理空间数据云提交任务一直在排队的问题,这个应该是官网的问题,不 ...

  7. 知网爬虫——爬取某个主题下的文章标题以及发表时间

    前几天帮朋友做了个知网的爬虫,爬取了"新闻传播"主题下的文章标题及发表时间:自己拖拖拉拉写了2天才写完,自己还是太弱了.个人认为这个作为一个练手的爬虫小项目还是不错的,于是写了主要 ...

  8. 【python】爬虫入门:代理IP池的使用、文件的写入与网易云爬取时的注意事项

    一.概述 在两天前实现利用爬虫爬取网易云音乐用户的各类公开信息之后,我对现有爬虫进行了功能上的增加.主要有: ①.使用代理IP池防止IP被封: ②.将爬取用户的听歌记录.歌单.关注.粉丝这四类数据的代 ...

  9. Day2-《青春有你2》选手信息爬取

    课程>我的课程>Python小白逆袭大神>[作业]Day2-<青春有你2>选手信息爬取 深度学习一般过程: 收集数据,尤其是有标签.高质量的数据是一件昂贵的工作. 爬虫的 ...

  10. 12306车站信息爬取(1)——输入条件的判断,包括出发站,到达站,和出发时间,并获取车次信息的链接

    12306车站信息的爬取是一个比较复杂的系统,爬取需要的信息不是很难,但是要将最终的结果做的完善和美观却不是那么容易.作为一个学习Python的新手,我想把练习和整理结合起来,希望大家可以相互交流和探 ...

最新文章

  1. CloudCompare的介绍
  2. MySQL子查询介绍
  3. java 与 c#的 中 字符串比较“==”与“equals”的差异
  4. 数据--第51课 - 二叉排序树
  5. 虚拟化这八年-【软件和信息服务】2014.11
  6. JAVA学习笔记:目录
  7. 程序员教你十分钟做出炫酷桌面
  8. 火狐浏览器国内版和国际版区别
  9. 支持linux的蓝牙键盘,可连接四款蓝牙设备的机械键盘 功能强大 不容小觑
  10. 如何整合JIRA、FishEye、Crucible进行CodeReview
  11. FPGA学习汇总(六)----数码管显示(1)
  12. 风袖电商之重构Theme业务对象
  13. 浅谈电池和充电方面的知识
  14. Oracle官网登录账号
  15. Vitas - star 歌词,拼音版
  16. 【Cesium】加载互联网地图服务——天地图
  17. 通过枚举驱动符号链接 判断程序***有几个实例在运行
  18. Druid监控页面配置用户密码、去除Ad
  19. 学渣考深大计算机,考深圳大学的研究生难吗?
  20. MTD系统架构和yaffs2使用、Nandflash驱动设计

热门文章

  1. elixir元编程的quote与unquote
  2. 在用mybatis时报错java.lang.AbstractMethodError: com.mysql.jdbc.ServerPreparedState
  3. R语言_缺失值NA的处理
  4. 正确的做事和做正确的事
  5. 自定制shell提示符
  6. matlab实验感悟,2019年matlab实验心得体会学习matlab的心得体会
  7. excel中indirect函数使用方法和应用实例
  8. 阿里云注册域名,购买云服务器,备案,域名解析图文教程
  9. 搭建jitsi的prosody出现的问题
  10. 算法的时间复杂度和空间复杂度详解