一 选题背景
本次项目选择了中国的厦门,通过了解厦门市二手房的情况,可以帮助人们在购房、出租等方面做出更明智的决策。可以帮助人们了解上海市经济的发展趋势。随着互联网的发展,越来越多的房地产信息通过网络发布,使用爬虫技术可以方便地收集和分析这些信息。而本次项目选择的数据来源是链家。链家是一家著名的房地产经纪公司,在厦门有着广泛的房地产业务。通过爬取厦门链家发布的二手房信息,可以获得丰富的数据,为分析提供参考。
2.
在现今毒外地务工人员洪流的影响下,拥有众多客户的链家网无疑是非常具有发展前景的,链家网顾客有许多的受众群体,普遍具有租房意向以及需求,这就代表着有许多的购买力能够产生较为不错的经济价值,在抓住了这些顾客的需求数据,能够发现更多顾客对于二手房源的具体需求进行分析,知晓二手房市场动态。
二 数据源的获取
厦门二手房信息爬虫
网址:https://xm.lianjia.com/ershoufang/
三 程序的实现
1、数据爬取与采集
data_list = [] #定义一个空的字典,用来储存爬取到的文本 for page in range(page_range): pgurl = url+'/pg'+str(page+1) print ("正在爬取的网页地址为:",pgurl) header = { 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.109 Safari/537.36'} page = requests.get(pgurl, headers=header) #访问网址获取该 html内容 a = page.text soup = BeautifulSoup(a,"lxml") #解析该html for b in soup.find_all('div',class_='info clear'): #find_all 找到 div class='info clear' 的标签 temp = [] for wz in b.find_all('div',class_= ['title','positionInfo','tag','houseInfo','priceInfo','followInfo']): temp.append(wz.get_text())
2、数据清洗和处理
tag = regnum(temp[2]) #截取了二手房在链家网上的发布时间以及关注人数 date = regnum(temp[3]) #有的二手房发布时间在1年以上,未用数字说明,此处说明其发布时间 date = addnone(date,2,'>365') #截取总价和单价 price = regnum(temp[5]) temp.extend(price)#extend() 函数用于在列表末尾一次性追加另一个序列中的多个值(用新列表扩展原来的列表) temp.extend(date) temp.extend(tag) #将二手房中未给出的数字描述统一赋值为0 temp = addnone(temp,15,'0') data_list.append(temp) def removenone(mylist):#移除参数中空值的函数 while '' in mylist: mylist.remove('') return mylist def addnone(mylist,length,cha):#对文本进行标准化,使其文本格式都一样 while len(mylist) < length: mylist.append(cha) return mylist def regnum(s):#提取爬取到的字符串中的数值 mylist = re.findall(r'[\d+\.\d]*', s) mylist = removenone(mylist) return mylist
效果:
1、文本分析,jieba分词和Wordcloud词云图
import jieba txt = open('房源信息.txt',encoding='utf-8').read() print(txt) #使用精确模式进行分词 count = jieba.lcut(txt) #定义空字典,对分词结果进行词频统计 remove_words = [u'的', u',',u'和', u'是', u'随着', u'对于', u'对',u'等',u'能',u'都',u'。',u' ',u' ',u'中',u'在',u'了', u'通常',u'如果',u',',u'\n'] # 自定义去除词库 word_count={} for word in count: if word not in remove_words: word_count[word] = word_count.get(word, 0) + 1 #按词频对分词进行排序 items = list(word_count.items()) items.sort(key=lambda x: x[1], reverse=True) print(items) # print(data1) wordcloud_1=( #实例化对象 WordCloud(init_opts=opts.InitOpts(theme=ThemeType.WESTEROS)) #设置图表主题 .add( series_name="", #设置图例名称,并没什么用 data_pair=items, #设置数据 word_size_range=[10,100], #字体大小范围 shape=SymbolType.ROUND_RECT) #样式 .set_global_opts( title_opts=opts.TitleOpts(title="词云图", #设置图表标题 # title_textstyle_opts=opts.TextStyleOpts(font_size=10) #设置标题的字体大小 ), tooltip_opts=opts.TooltipOpts(is_show=True), ) ).render('房源词云图.html')
效果:
四 数据分析可视化
1.排名前十的地区平均房价折线图
line_1=( #实例化图表 Line(init_opts=opts.InitOpts(theme=ThemeType.WESTEROS)) #设置图表主题 .add_xaxis(data5['Position'].tolist()) #设置横坐标 .add_yaxis("总价",data5['总价'].tolist(), markpoint_opts=opts.MarkPointOpts(data=[opts.MarkPointItem(type_="max")])) #设置纵坐标1、突出显示最大值或者最小值 .set_global_opts( #全局配置 title_opts=opts.TitleOpts(title="排名前十的地区平均房价折线图") #图表标题 ) ).render('排名前十的地区平均房价折线图.html')
效果:
2.排名前十的地区房源数量折线图
line_2=( #实例化图表 Line(init_opts=opts.InitOpts(theme=ThemeType.WESTEROS)) #设置图表主题 .add_xaxis(data1['Position'].tolist()) #设置横坐标 .add_yaxis("数量",data1['Title'].tolist(), markpoint_opts=opts.MarkPointOpts(data=[opts.MarkPointItem(type_="max")])) #设置纵坐标1、突出显示最大值或者最小值 .set_global_opts( #全局配置 title_opts=opts.TitleOpts(title="排名前十的地区房源数量折线图") #图表标题 ) ).render('排名前十的地区房源数量折线图.html')
效果:
3.最受欢迎户型分布
bar = ( Bar() .add_xaxis(data2['几室'].tolist()) .add_yaxis("几室",data2['Title'].tolist()) .add_yaxis("几厅",data3['Title'].tolist()) .set_global_opts(title_opts=opts.TitleOpts(title="最受欢迎户型分布", subtitle="副标题"), toolbox_opts=opts.BrushOpts(),) ) bar.render('最受欢迎户型分布.html')
效果:
4.不同建造年份待售房占比
pie.set_global_opts( #标题配置项 title_opts=opts.TitleOpts(title="不同建造年份待售房占比",pos_left='70%'), # 图例配置项 legend_opts=opts.LegendOpts( type_="scroll" , pos_top="20%" , pos_left="80%" , orient="vertical" ), ) pie.render('不同建造年份待售房占比.html')
效果:
5、一元线性回归预测房价
from sklearn.linear_model import LinearRegression model = LinearRegression() x = data['面积'].values.reshape(-1, 1)#reshape(-1,1)转换成1列 y = data['总价'] model.fit(x, y) print((model.predict([[600]])).round(2))#预测600平总价 import matplotlib.pyplot as plt plt.scatter(data['面积'], y, color='blue') plt.plot(x, model.predict(x), 'r-') plt.grid(True) plt.show()
效果:
四 总结
通过这次的的爬虫实验分析,得到了一个厦门二手房源的信息,这对于即将毕业的我来说还是非常有用的让我在找房源的时候有了一个较为初步的判断信息,避免了不必要的麻烦,在选择上也有着较为详细的房源选择,不仅可以根据排名来选择而且还可以根据欢迎程度选择自己想要的房源。
在这次爬虫实验中,虽然在刚开始的时候真的是无从下手不知道该做什么方向的课题,不过好在从各种的资料中确定了方向,这次的课程设计不仅锻炼了我的整体构架思维,还提升了解决问题的能力,受益良多。
整体代码
1.爬取数据
import re import requests from bs4 import BeautifulSoup import pandas as pd def removenone(mylist):#移除参数中空值的函数 while '' in mylist: mylist.remove('') return mylist def addnone(mylist,length,cha):#对文本进行标准化,使其文本格式都一样 while len(mylist) < length: mylist.append(cha) return mylist def regnum(s):#提取爬取到的字符串中的数值 mylist = re.findall(r'[\d+\.\d]*', s) mylist = removenone(mylist) return mylist def lianjia(url,page_range,district): #Initialization colum_name=['Title','Position','Tag','followInfo','VR','Info', '总价','单价RMB/万','单价(后三位)','关注人数', '发布时间','几室','几厅','面积','楼层','年份'] #定义爬取到的文本的表头 data_list = [] #定义一个空的字典,用来储存爬取到的文本 for page in range(page_range): pgurl = url+'/pg'+str(page+1) print ("正在爬取的网页地址为:",pgurl) header = { 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.109 Safari/537.36'} page = requests.get(pgurl, headers=header) #访问网址获取该 html内容 a = page.text soup = BeautifulSoup(a,"lxml") #解析该html for b in soup.find_all('div',class_='info clear'): #find_all 找到 div class='info clear' 的标签 temp = [] for wz in b.find_all('div',class_= ['title','positionInfo','tag','houseInfo','priceInfo','followInfo']): temp.append(wz.get_text()) #截取二手房中的房间数,面积,楼层,建造时间 tag = regnum(temp[2]) #截取了二手房在链家网上的发布时间以及关注人数 date = regnum(temp[3]) #有的二手房发布时间在1年以上,未用数字说明,此处说明其发布时间 date = addnone(date,2,'>365') #截取总价和单价 price = regnum(temp[5]) temp.extend(price)#extend() 函数用于在列表末尾一次性追加另一个序列中的多个值(用新列表扩展原来的列表) temp.extend(date) temp.extend(tag) #将二手房中未给出的数字描述统一赋值为0 temp = addnone(temp,15,'0') data_list.append(temp) print("爬取完成") # print(data_list) data = pd.DataFrame(data_list,columns=colum_name)#将data转换为dataframe类型 data.to_csv(district+'.csv') #保存数据到CSV文件 return data if __name__ == '__main__': district_list = [(input('请输入保存文件英文名:'))] #输入 for district in district_list: url = "https://xm.lianjia.com/ershoufang/" page_range = int(input('请输入爬取页数:')) #输入获得翻页数量 my = lianjia(url,page_range,district)
2.可视化
import pandas as pd import numpy as np from pyecharts.charts import Bar,Pie,WordCloud,Line #导入图表类型 from pyecharts import options as opts #导入相关属性包 from pyecharts.charts import Page,Grid #导入页面编排包 from pyecharts.globals import ThemeType #导入主题包 from pyecharts.globals import SymbolType #词云图样式 from pyecharts.globals import ChartType data=pd.read_csv('xiamen.csv',encoding='utf-8') data.fillna(value=0,inplace=True) data['Position']=data['Position'].str.replace(' ','') data['Position']=data['Position'].str.split('-',expand=True)[1] data1=data.groupby(by=['Position'])['Title'].count().reset_index().sort_values(['Title'])[-5:]#排名前十的区域房源数量 data2=data.groupby(by=['几室'])['Title'].count().reset_index().sort_values(['Title'])[-5:] data3=data.groupby(by=['几厅'])['Title'].count().reset_index().sort_values(['Title'])[-5:] data2['几室']=data2['几室'].astype('str')+'室'+data3['几厅'].astype('str')+'厅' data4=data.groupby(by=['年份'])['Title'].count().reset_index().round(0) data5=data.groupby(by=['Position'])['总价'].mean().reset_index().sort_values(['总价'])[-10:].round(0) data6=data['Title'].tolist() print(data6) line_1=( #实例化图表 Line(init_opts=opts.InitOpts(theme=ThemeType.WESTEROS)) #设置图表主题 .add_xaxis(data5['Position'].tolist()) #设置横坐标 .add_yaxis("总价",data5['总价'].tolist(), markpoint_opts=opts.MarkPointOpts(data=[opts.MarkPointItem(type_="max")])) #设置纵坐标1、突出显示最大值或者最小值 .set_global_opts( #全局配置 title_opts=opts.TitleOpts(title="排名前十的地区平均房价折线图") #图表标题 ) ).render('排名前十的地区平均房价折线图.html') line_2=( #实例化图表 Line(init_opts=opts.InitOpts(theme=ThemeType.WESTEROS)) #设置图表主题 .add_xaxis(data1['Position'].tolist()) #设置横坐标 .add_yaxis("数量",data1['Title'].tolist(), markpoint_opts=opts.MarkPointOpts(data=[opts.MarkPointItem(type_="max")])) #设置纵坐标1、突出显示最大值或者最小值 .set_global_opts( #全局配置 title_opts=opts.TitleOpts(title="排名前十的地区房源数量折线图") #图表标题 ) ).render('排名前十的地区房源数量折线图.html') bar = ( Bar() .add_xaxis(data2['几室'].tolist()) .add_yaxis("几室",data2['Title'].tolist()) .add_yaxis("几厅",data3['Title'].tolist()) .set_global_opts(title_opts=opts.TitleOpts(title="最受欢迎户型分布", subtitle="副标题"), toolbox_opts=opts.BrushOpts(),) ) bar.render('最受欢迎户型分布.html') pie=Pie() pie.add("",[list(z) for z in zip(data4['年份'].tolist(),data4['Title'].tolist())] #数据标签展示 ,label_opts=opts.LabelOpts( position="outside", formatter="{d}%")) # 设置其他配置项 pie.set_global_opts( #标题配置项 title_opts=opts.TitleOpts(title="不同建造年份待售房占比",pos_left='70%'), # 图例配置项 legend_opts=opts.LegendOpts( type_="scroll" , pos_top="20%" , pos_left="80%" , orient="vertical" ), ) pie.render('不同建造年份待售房占比.html') #一元回归预测 from sklearn.linear_model import LinearRegression model = LinearRegression() x = data['面积'].values.reshape(-1, 1)#reshape(-1,1)转换成1列 y = data['总价'] model.fit(x, y) print((model.predict([[600]])).round(2))#预测600平总价 import matplotlib.pyplot as plt plt.scatter(data['面积'], y, color='blue') plt.plot(x, model.predict(x), 'r-') plt.grid(True) plt.show() str="\n" f=open('房源信息.txt','w',encoding='utf-8') f.write(str.join(data6)) f.close() import jieba txt = open('房源信息.txt',encoding='utf-8').read() print(txt) #使用精确模式进行分词 count = jieba.lcut(txt) #定义空字典,对分词结果进行词频统计 remove_words = [u'的', u',',u'和', u'是', u'随着', u'对于', u'对',u'等',u'能',u'都',u'。',u' ',u' ',u'中',u'在',u'了', u'通常',u'如果',u',',u'\n'] # 自定义去除词库 word_count={} for word in count: if word not in remove_words: word_count[word] = word_count.get(word, 0) + 1 #按词频对分词进行排序 items = list(word_count.items()) items.sort(key=lambda x: x[1], reverse=True) print(items) # print(data1) wordcloud_1=( #实例化对象 WordCloud(init_opts=opts.InitOpts(theme=ThemeType.WESTEROS)) #设置图表主题 .add( series_name="", #设置图例名称,并没什么用 data_pair=items, #设置数据 word_size_range=[10,100], #字体大小范围 shape=SymbolType.ROUND_RECT) #样式 .set_global_opts( title_opts=opts.TitleOpts(title="词云图", #设置图表标题 # title_textstyle_opts=opts.TextStyleOpts(font_size=10) #设置标题的字体大小 ), tooltip_opts=opts.TooltipOpts(is_show=True), ) ).render('房源词云图.html')
标签:课程设计,mylist,temp,title,python,爬取,word,data,opts From: https://www.cnblogs.com/songjian49/p/17002765.html