网络爬虫项目实战 教案 项目六 房产Requests+Parsel+MTC项目实战_第1页
网络爬虫项目实战 教案 项目六 房产Requests+Parsel+MTC项目实战_第2页
网络爬虫项目实战 教案 项目六 房产Requests+Parsel+MTC项目实战_第3页
网络爬虫项目实战 教案 项目六 房产Requests+Parsel+MTC项目实战_第4页
网络爬虫项目实战 教案 项目六 房产Requests+Parsel+MTC项目实战_第5页
已阅读5页,还剩14页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

教师备课纸苏州工业职业技术学院教师备课纸SuzhouInstituteOfIndustrialTechnology第

PAGE

19页教师备课首页苏州工业职业技术学院教师备课首页SuzhouInstituteOfIndustrialTechnology第1页课题项目六房产Requests+Parsel+MTC项目实战课型理实一体授课班级大数据22C1、大数据22C2授课时数8教学目标(1)掌握Requests+Parsel爬虫用法。(2)掌握XPath语法格式。(3)掌握CSS选择器。(4)掌握从CSV文件读取到DataFrame。(5)掌握DataFrame去重去空方法。(6)掌握DataFrame列裂变。(7)掌握DataFrame保存到CSV文件。(8)掌握文件导入MySQL数据库。(9)掌握Flask搭建数据可视化服务。(10)了解ECharts柱状图和折线图。教学重点(1)掌握XPath语法格式。(2)掌握CSS选择器。(3)掌握Flask框架可视化图表。教学难点Flask框架可视化图表学情分析学生零基础,在教学中注重引导学生学会自主学习,培养学生学会查找文献资料教学效果教后记任务1:Requests+Parsel采集数据Parsel是一个Python的第三方库,可以解析HTML和XML,并支持使用XPath和CSS选择器对内容进行提取和修改,同时还融合了正则表达式的提取功能。下面以爬取某房产网站为例,介绍Requests配合Parsel采集租房数据的详细步骤。步骤1:转到Tomcat安装目录下的bin目录,运行startup.bat后,打开Chrome,访问:50001/findhouse/index1.html,显示网站页面,代表Tomcat运行正常。步骤2:打开PyCharm,File->NewProject创建PyCharm项目rent-house,手工填写项目路径,选择Anaconda编译器(python.exe)。点击“Create”按钮,创建空项目rent-house。步骤3:打开网站页面(:50001/findhouse/index1.html),在页面任意位置点击鼠标右键后,选择“检查”,选择“Network”选项卡,查看HTTP请求和返回内容。点击“Clear”按钮,清除缓存,同时按下Ctrl+R,重新加载页面。切换到“Doc”选项卡后,左侧选择“index1.html”,查看RequestHeaders,保存User-Agent、cookie(如果有的话)、referer(如果有的话)3个属性值。步骤4:在项目根目录下New->PythonFile,创建spider.py。在spider.py中,定义get_page函数,headers的“User-Agent”值使用上面RequestHeaders复制过来的内容。#-*-coding:UTF-8-*-importcsvimportrandomimportrefromtimeimportsleepimportrequestsfromlxmlimportetreefromparselimportSelectorfromrequests.utilsimportget_encodings_from_content#获取网页源码defget_page(url):#设置请求头信息headers={'Cookie':'','User-Agent':'Mozilla/5.0(WindowsNT10.0;Win64;x64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/Safari/537.36'}#发送get请求html=requests.get(url,headers=headers)#查看编码方式enconding=get_encodings_from_content(html.text)#打印网页内容html_doc=html.content.decode(enconding[0])#返回网页源码returnhtml_doc步骤5:打开网站页面(:50001/findhouse/index1.html),鼠标停留在第1条租房信息,然后点击鼠标右键后,选择“检查”,查看租房信息的XPath路径,一对li标签对应一条租房信息,先使用CSS选择器获取到所有class为“listUnit-date”的li标签,再依次遍历这个li标签,获取li标签中租房的各项信息。步骤6:在当前页面,鼠标停留在第1条租房信息中间的文本信息块部分,然后点击鼠标右键后,选择“检查”,查找房屋信息块的XPath路径。房屋文本信息块在li标签中class为“pro-text”的div标签中,房屋文本信息块对应的CSS选择器为“.pro-text”。步骤7:在当前页面,鼠标停留在第1条租房信息的标题部分,然后点击鼠标右键后,选择“检查”,查找标题的XPath路径。标题在class为“list-pic-title”的div标签中,h3标签下的a标签中。标题对应的CSS选择器为“.list-pic-titleh3a::text”。步骤8:在当前页面,鼠标停留在第1条租房信息的详细信息部分,然后点击鼠标右键后,选择“检查”,查找详细信息的XPath路径。详细信息在class为“list-pic-ps”的p标签下的span标签中。详细信息对应的CSS选择器为“.list-pic-psspan::text”。步骤9:详细信息中含区域、房屋类型、房屋结构、面积和朝向,使用split()进行切分得到具体的分项信息,朝向信息缺失的使用空字符串赋值。步骤10:类似上述步骤,查找离公共交通距离和价格的XPath路径,得到离公共交通距离的CSS选择器为“.list-pic-ad::text”,价格的CSS选择器为“.price-itemsdivspan::text”。步骤11:在spider.py中增加parse_page函数,初始化parsel.Selector()对象,获取到所有class为“listUnit-date”的li标签,从li标签中提取出租房的标题、区域、房屋类型、房屋结构、面积、朝向、交通距离和价格信息。将8个字段信息组合成字典,保存租房信息至house_raw.csv文件中。#爬取数据defparse_page(url):#获取网页源码html=get_page(url)#暂停1~3秒的整数秒,时间区间:[1,3]sleep(random.randint(1,3))#初始化parsel.Selector()对象selector=Selector(html)#获取到所有class为listUnit-date的li标签node_list=selector.css("li.listUnit-date")#打印获取到的标签数量print(len(node_list))#遍历li标签,获取li标签中租房的各项信息fornodeinnode_list:#房屋信息块info=node.css(".pro-text")#标题title=info.css(".list-pic-titleh3a::text").get().strip()#详细信息detail=info.css(".list-pic-psspan::text").getall()detail[1]=re.sub("\\s+","",detail[1])contents=detail[1].split("|")#区域district=contents[0].strip()#房屋类型house_type=contents[1].strip()#房屋结构structure=contents[2].strip()#面积area=contents[3].strip()#朝向if(len(contents)<5):direction=""else:direction=contents[-1].strip()#离公共交通距离distance=info.css(".list-pic-ad::text").getall()#替换连续空格到单个空格if(len(distance)==0):distance=""if(len(distance)==1):distance=re.sub("\\s+","",distance[0].strip())if(len(distance)==2):distance=re.sub("\\s+","",distance[1].strip())#价格price=node.css(".price-itemsdivspan::text").get()#组合成字典dict={'标题':title,'区域':district,'房屋类型':house_type,'房屋结构':structure,'面积':area,'朝向':direction,'交通距离':distance,'价格':price}#保存商品信息withopen('house_raw.csv','a',newline="",encoding='utf-8')asf:csv_write=csv.writer(f)csv_write.writerow([title,district,house_type,structure,area,direction,distance,price])步骤12:在spider.py中定义主函数,设置爬取网站的起始页。if__name__=='__main__':#获取起始页源码base_url=":50001/findhouse/index1.html"parse_page(base_url)步骤13:运行spider.py,应该在项目根目录下看到文件house_raw.csv。打开house_raw.csv,看到如下结果:城家公寓北京回龙观霍营地铁站店2楼,昌平-回龙观,公寓,一居室C房东直租+免中介费+整租房型,14M²,朝北,距离8号线霍营地铁站724米,3800元柚米寓(北京旭辉26街区店)5楼,顺义-顺义城区,公寓,复式简约一居室房型,21M²,朝南,距离15号线南法信地铁站562米,2530元魔方公寓(百子湾店)2楼,朝阳-百子湾,公寓,开间朝南房型,25M²,朝南,距离7号线百子湾地铁站803米,3990元魔方公寓(百子湾店)2楼,朝阳-百子湾,公寓,开间朝北房型,25M²,朝北,距离7号线百子湾地铁站803米,3507元泊寓西直门店5楼,海淀-小西天,公寓,一室户D配楼房型,25M²,众多朝向,距离2号线西直门地铁站1138米,5997.2元泊寓西直门店2楼,海淀-小西天,公寓,一室户A房型,15M²,众多朝向,距离2号线西直门地铁站1138米,4756.4元泊寓西直门店8楼,海淀-小西天,公寓,一室户D房型,24M²,众多朝向,距离2号线西直门地铁站1138米,6514.2元泊寓(亦庄店)1楼,通州-次渠,公寓,LOFT房型,24M²,众多朝向,距离亦庄线经海路地铁站652米,2600元泊寓西直门店2楼,海淀-小西天,公寓,COUPLE房型,35M²,众多朝向,距离2号线西直门地铁站1138米,6930元柚米寓(北京旭辉26街区店)8楼,顺义-顺义城区,公寓,飘窗复式中户型房型,30M²,朝北,距离15号线南法信地铁站562米,3380元柚米寓(北京旭辉26街区店)3楼,顺义-顺义城区,公寓,双窗复式两居室房型,50M²,朝东,距离15号线南法信地铁站562米,4490元泊寓成寿寺社区3楼,丰台-宋家庄,公寓,standard房型,29M²,朝东,距离14号线东段方庄地铁站821米,4558元城家公寓北京回龙观霍营地铁站店1楼,昌平-回龙观,公寓,一居室A房东直租+免中介费+整租房型,13M²,众多朝向,距离8号线霍营地铁站724米,3400元泊寓(亦庄店)2楼,通州-次渠,公寓,Studio房型,20M²,朝南,距离亦庄线经海路地铁站652米,2800元泊寓(亦庄店)5楼,通州-次渠,公寓,StudioL房型,25M²,朝北,距离亦庄线经海路地铁站652米,3100元上面结果显示15条记录,恰好是1页数据,接下来继续增强爬虫,让它具有翻页爬取功能。步骤14:打开起始页,滑动页面到最底端,鼠标停留在最后一页的页码“5”,然后点击鼠标右键后,选择“检查”,查看页码“5”的XPath路径为“//span[@class="pageBtnWrap"]/a[last()-1]/text()”,通过对多页网址进行分析,找到网址的规律:index+数字序列。步骤15:修改spider.py,使爬虫具有翻页爬取功能。if__name__=='__main__':#获取起始页源码#base_url=":50001/findhouse/index1.html"parse_page(base_url)#找到总页数first_page_doc=get_page(base_url)first_page_tree=etree.HTML(first_page_doc)page_num=first_page_tree.xpath('//span[@class="pageBtnWrap"]/a[last()-1]/text()')page_num=(int)(page_num[0])iflen(page_num)>0else0ifpage_num:page_num=(int)(page_num)#爬取多页foriinrange(1,page_num+1):current_url=f":50001/findhouse/index{i}.html"parse_page(current_url)运行spider.py,打开house_raw.csv。打开文件,看到如下结果:城家公寓北京回龙观霍营地铁站店2楼,昌平-回龙观,公寓,一居室C房东直租+免中介费+整租房型,14M²,朝北,距离8号线霍营地铁站724米,3800元柚米寓(北京旭辉26街区店)5楼,顺义-顺义城区,公寓,复式简约一居室房型,21M²,朝南,距离15号线南法信地铁站562米,2530元魔方公寓(百子湾店)2楼,朝阳-百子湾,公寓,开间朝南房型,25M²,朝南,距离7号线百子湾地铁站803米,3990元魔方公寓(百子湾店)2楼,朝阳-百子湾,公寓,开间朝北房型,25M²,朝北,距离7号线百子湾地铁站803米,3507元泊寓西直门店5楼,海淀-小西天,公寓,一室户D配楼房型,25M²,众多朝向,距离2号线西直门地铁站1138米,5997.2元柚米寓(北京旭辉26街区店)9楼,顺义-顺义城区,公寓,地铁直达望京房型,48M²,朝东,距离15号线南法信地铁站562米,4200元柚米寓(北京旭辉26街区店)4楼,顺义-顺义城区,公寓,白领单身公寓房型,20M²,朝南,距离15号线南法信地铁站562米,2601元柚米寓(北京旭辉26街区店)1楼,顺义-顺义城区,公寓,过道窗户型房型,24M²,朝东,距离15号线南法信地铁站562米,2575元柚米寓(北京旭辉26街区店)4楼,顺义-顺义城区,公寓,温馨复式一居房型,27M²,朝西,距离15号线南法信地铁站562米,3308元柚米寓(北京旭辉26街区店)5楼,顺义-顺义城区,公寓,空港朝北开间房型,21M²,朝北,距离15号线南法信地铁站562米,2662元任务2:Pandas清洗数据任务1的输出结果显示91条记录,其中前15条是重复数据,需要删除。另外,字段“面积”和“价格”单位需要删除。接下来,采用Pandas完成数据清洗任务。步骤1:在项目根目录New->PythonFile,创建data_clean.py,读入house_raw.csv到DataFrame类型。#-*-coding:UTF-8-*-importpandasaspd#读入csv文件到Dataframe对象labels=['标题','区域','房屋类型','房屋结构','面积','朝向','交通距离','价格']df=pd.read_csv("house_raw.csv",names=labels,encoding='utf-8')print(df.shape)print(df.head())运行data_clean.py,PyCharm控制台输出如下结果:标题区域房屋类型...朝向交通距离价格0城家公寓北京回龙观霍营地铁站店2楼昌平-回龙观公寓...朝北距离8号线霍营地铁站724米3800元1柚米寓(北京旭辉26街区店)5楼顺义-顺义城区公寓...朝南距离15号线南法信地铁站562米2530元2魔方公寓(百子湾店)2楼朝阳-百子湾公寓...朝南距离7号线百子湾地铁站803米3990元3魔方公寓(百子湾店)2楼朝阳-百子湾公寓...朝北距离7号线百子湾地铁站803米3507元4泊寓西直门店5楼海淀-小西天公寓...众多朝向距离2号线西直门地铁站1138米5997.2元步骤2:完善data_clean.py,删除重复记录,剔除缺失值。#去重df=df.drop_duplicates()#剔除缺失值df=df.dropna()print(df.shape)运行data_clean.py,PyCharm控制台输出如下结果:(42,8)步骤3:完善data_clean.py,从“标题”列抽取出小区和楼层。#标题裂变为2列df['小区']=df['标题'].apply(lambdax:x.split('')[0])df['小区']=df['小区'].str.replace('(.*?)','')df['楼层']=df['标题'].apply(lambdax:x.split('')[1])print(df[["小区","楼层"]].head())运行data_clean.py,PyCharm控制台输出如下结果:小区楼层0城家公寓北京回龙观霍营地铁站店2楼1柚米寓5楼2魔方公寓2楼3魔方公寓2楼4泊寓西直门店5楼步骤4:完善data_clean.py,从“区域”列抽取出区和域。#区域裂变为2列df['区']=df['区域'].apply(lambdax:x.split('-')[0])df['域']=df['区域'].apply(lambdax:x.split('-')[1])print(df[["区","域"]].head())运行data_clean.py,PyCharm控制台输出如下结果:区域0昌平回龙观1顺义顺义城区2朝阳百子湾3朝阳百子湾4海淀小西天步骤5:完善data_clean.py,去除“面积”和“价格”字段的单位后缀。#去除单位df['面积']=df['面积'].apply(lambdax:x[:-2])df['价格']=df['价格'].apply(lambdax:x[:-1])print(df[["面积","价格"]].head())运行data_clean.py,PyCharm控制台输出如下结果:面积价格01438001212530225399032535074255997.2步骤6:完善data_clean.py,去除多余列并更新索引。#去除多余列df=df.drop(['标题','区域'],axis=1)#更新索引df=df.reset_index(drop=True)df.index=df.index+1print(df.shape)print(df.head())运行data_clean.py,PyCharm控制台输出如下结果:(42,10)房屋类型房屋结构面积朝向...小区楼层区域1公寓一居室C房东直租+免中介费+整租房型14朝北...城家公寓北京回龙观霍营地铁站店2楼昌平回龙观2公寓复式简约一居室房型21朝南...柚米寓5楼顺义顺义城区3公寓开间朝南房型25朝南...魔方公寓2楼朝阳百子湾4公寓开间朝北房型25朝北...魔方公寓2楼朝阳百子湾5公寓一室户D配楼房型25众多朝向...泊寓西直门店5楼海淀小西天步骤7:完善data_clean.py,保存清洗后的数据。#保存为csv文件df.to_csv("house_clean.csv",index_label=”id”)任务3:MySQL存储数据下面要转到MySQL,把净化后的数据导入MySQL。步骤1:使用Navicat软件,创建数据库house。步骤2:打开house数据库,新建查询后创建表house_info。CREATETABLEhouse_info(idINT,house_typeVARCHAR(20),structureVARCHAR(20),areaINT,directionVARCHAR(20),distanceVARCHAR(50),priceINT,addrVARCHAR(20),floorVARCHAR(20),districtVARCHAR(20),roadVARCHAR(20),PRIMARYKEY(id))charset=utf8;步骤3:查看MySQL上传目录。SHOWVARIABLESLIKE'%secure_file_priv%';步骤4:复制house_clean.csv到MySQL上传目录。步骤5:在MySQL上传目录中,选择house_clean.csv文件,右键选择“属性”->“安全”->“对象名称”,复制文件的绝对路径。如果house_clean.csv绝对路径包含中文路径,要把文件复制到绝对路径只包含英文的位置,然后通过选择文件->右键选择“属性”->“安全”->“对象名称”,复制文件绝对路径。步骤6:将清洗后的csv文件导入house_info表中,路径中的“\”要换成“\\”,因为“\”在MySQL中是转义符。LOADDATALOCALINFILE"C:\\ProgramData\\house_clean.csv"INTOTABLEhouse_infoCHARACTERSETutf8FIELDSTERMINATEDBY','OPTIONALLYENCLOSEDBY'"'LINESTERMINATEDBY'\r\n'IGNORE1LINES(id,house_type,structure,area,direction,distance,price,addr,floor,district,road);步骤7:执行select语句,检查前5条记录。select*fromhouse_infolimit5;任务4:Flask搭建服务数据存入MySQL数据库后,下面采用Flask搭建MTC应用。步骤1:在项目根目录New->PythonPackage,创建app包。步骤2:在app包下New->PythonPackage,创建views包。步骤3:在app包下New->Directory,创建目录static,然后把echarts.min.js复制到app/static目录。步骤4:在app包下New->PythonFile,创建extensions.py,定义db变量和config_extensions方法。#-*-coding:UTF-8-*-fromflask_sqlalchemyimportSQLAlchemydb=SQLAlchemy()defconfig_extensions(app):db.init_app(app)步骤5:在app/views包下New->PythonFile,创建main.py,定义blueprint变量。#-*-coding:UTF-8-*-fromflaskimportBlueprintblueprint=Blueprint("main",__name__)步骤6:完善app/views/__init__.py,定义DEFAULT_BLUEPRINT变量。#-*-coding:UTF-8-*-fromapp.views.mainimportblueprintDEFAULT_BLUEPRINT=((blueprint,""))步骤7:完善app/__init__.py,定义Config类、config_blueprint方法、create_app方法。#-*-coding:UTF-8-*-fromflaskimportFlaskfromapp.extensionsimportconfig_extensionsfromapp.viewsimportblueprintclassConfig:SQLALCHEMY_COMMIT_ON_TEARDOWN=TrueSQLALCHEMY_TRACK_MODIFICATIONS=FalseSQLALCHEMY_DATABASE_URI="mysql+pymysql://root:123456@:3306/house?charset=utf8"defconfig_blueprint(app):app.register_blueprint(blueprint,url_prefix="")defcreate_app(config):app=Flask(__name__)app.config.from_object(config)config_extensions(app)config_blueprint(app)returnapp检查用户名、密码和端口,确认输入值和安装的MySQL一致,确认连接地址中的数据库名称与MySQL中创建的数据库名称一致。步骤8:在app包下New->PythonFile,创建manager.py。#-*-coding:UTF-8-*-fromflask_scriptimportManager,Serverfromappimportcreate_app,Configif__name__=='__main__':app=create_app(Config)manager=Manager(app)manager.add_command('runserver',Server(host='',use_debugger=True,use_reloader=True))manager.run()右键选中manager.py,选择“RunManager”菜单,运行程序,控制台出现下面结果。在菜单Run->EditConfiguration,选中manager,编辑Parameters,填写“runserver”。再次右键选中manager.py,选择“RunManager”菜单,运行程序。控制台出现下面结果,代表Flask配置成功。单击“停止”按钮,停止manager运行。步骤9:在app包下New->PythonPackage,创建包models。步骤10:在包app/models下New->PythonFile,创建entities.py,定义House类。#-*-coding:UTF-8-*-fromapp.extensionsimportdb#定义House类classHouse(db.Model):__tablename__='house_info'id=db.Column(db.Integer,primary_key=True)#楼层floor=db.Column(db.String(20))#租金price=db.Column(db.Integer)#区district=db.Column(db.String(20))步骤11:完善app/models/__init__.py,开放House类。#-*-coding:UTF-8-*-from.entitiesimportHouse步骤12:完善app/views/main.py,定义get_house_num_by_district和api_house_num方法。#-*-coding:UTF-8-*-fromflaskimportBlueprint,jsonifyfromsqlalchemyimportfunc,textfromapp.extensionsimportdbfromapp.modelsimportHouseblueprint=Blueprint("main",__name__)defget_house_num_by_district():rows=db.session.query(House.district,func.count().label('count')).group_by('district').order_by(text('countdesc')).limit(5)x=[]y=[]forrowinrows:x.append(row[0])y.append(row[1])returnx,y@blueprint.route("/api/house_num")defapi_house_num():x,y=get_house_num_by_district()returnjsonify([x,y])步骤13:运行app/manager.py,打开Chrome,访问:5000/api/house_num,从服务器返回租房数据的列表,表示Flask连接数据库正常。任务5:Flask+ECharts可视化数据有了Flask提供的数据,采用ECharts框架的柱状图完成区房源数的统计显示。步骤1:完善app/views/main.py,增加定义house_num方法。#-*-coding:UTF-8-*-fromflaskimportBlueprint,jsonify,render_templatefromsqlalchemyimportfunc,textfromapp.extensionsimportdbfromapp.modelsimportHouseblueprint=Blueprint("main",__name__)defget_house_num_by_district():rows=db.session.query(House.district,func.count(1).label('count')).group_by('district').order_by(text('countdesc')).limit(5)x=[]y=[]forrowinrows:x.append(row[0])y.append(row[1])returnx,y@blueprint.route("/api/house_num")defapi_house_num():x,y=get_house_num_by_district()returnjsonify([x,y])@blueprint.route("/house_num")defhouse_num():x,y=get_house_num_by_district()returnrender_template('single_chart.html',x_data=x,y_data=y)步骤2:在app包下N

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论