【Python】实现爬虫(完整版),爬取天气数据并进行可视化分析

张开发
2026/4/21 14:55:22 15 分钟阅读
【Python】实现爬虫(完整版),爬取天气数据并进行可视化分析
往期源码回顾:【C】图书管理系统(完整板)【C】实现图书管理系统Qt C GUI界面版进入今天的正题1.实现需求从网上(随便一个网址我爬的网址会在评论区告诉大家dddd获取某一年的历史天气信息包括每天最高气温、最低气温、天气状况、风向等完成以下功能 1将获取的数据信息存储到csv格式的文件中文件命名为”城市名称.csv”,其中每行数据格式为“日期最高温最低温天气风向” 2在数据中增加“平均温度”一列其中平均温度最高温最低温/2在同一张图中绘制两个城市一年平均气温走势折线图 3统计两个城市各类天气的天数并绘制条形图进行对比假设适合旅游的城市指数由多云天气占比0.3晴天占比0.4阴天数占比0.3试比较两个城市中哪个城市更适合旅游 4统计这两个城市每个月的平均气温绘制折线图并通过折线图分析该城市的哪个月最适合旅游 5统计出这两个城市一年中平均气温在18~25度风力小于5级的天数并假设该类天气数越多城市就越适宜居住判断哪个城市更适合居住2025年3月2日更新爬取网址新增了查看更多选项导致我们爬取数据时每个月份的数据爬取不全为了解决这个问题我们需要使用selenium中的webdriver模拟用户点击查看更多之后再获取整个页面再进行解析就可以获取全部数据了。因此代码有所更新。爬虫代码:importrandomimporttimefromspider.data_storageimportDataStoragefromspider.html_downloaderimportHtmlDownloaderfromspider.html_parserimportHtmlParserclassSpiderMain:def__init__(self):self.html_downloaderHtmlDownloader()self.html_parserHtmlParser()self.data_storageDataStorage()defstart(self): 爬虫启动方法 将获取的url使用下载器进行下载 将html进行解析 数据存取 :return: foriinrange(1,13):# 采用循环的方式进行依次爬取time.sleep(random.randint(0,10))# 随机睡眠0到40s防止ip被封urlXXXXhtmlself.html_downloader.download(url)resultWeatherself.html_parser.parser(html)resultWeather.insert(0,t)self.data_storage.storage(resultWeather)if__name____main__:mainSpiderMain()main.start()importrequestsasrequestsclassHtmlDownloader:defdownload(self,url): 根据给定的url下载网页 :param url: :return: 下载好的文本 headers{User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:101.0) Gecko/20100101 Firefox/101.0}resultrequests.get(url,headersheaders)returnresult.content.decode(utf-8)此处大家需要注意将User-Agent换成自己浏览器访问该网址的具体如何查看呢其实很简单只需大家进入网站后右键网页然后点击检查将出现这样的界面然后只需再点击网络再随便点击一个请求如下图就可以进入如下图然后再复制图中User-Agent的内容就好了继续from bs4importBeautifulSoupclassHtmlParser:defparser(self,html): 解析给定的html:param html::return:area set weather[]bsBeautifulSoup(html,html.parser)bodybs.body # 获取html中的body部分 uldiv.find(ul)# 获取div中的ul/ulliul.find_all(li)# 获取ul中的所有li/liforl in li:tempWeather[]div1l.find_all(div)# 获取当前li中的所有divfori in div1:tempStri.string.replace(℃,)# 将℃进行替换 tempStrtempStr.replace( ,)# 替换空格 tempWeather.append(tempStr)weather.append(tempWeather)returnweatherimportpandasas pdclassDataStorage:defstorage(self,weather): 数据存储:param weather list:return: datapd.DataFrame(columnsweather[0],dataweather[1:])# 格式化数据 data.to_csv(C:\\Users\\86183\\Desktop\\成都.csv,indexFalse,sep,,modea)# 保存到csv文件当中可视化代码importpandasaspdimportmatplotlibasmplimportnumpyasnpimportmatplotlib.pyplotasplt plt.rcParams[font.sans-serif][SimHei]# 设置字体plt.rcParams[axes.unicode_minus]False# 该语句解决图像中的“-”负号的乱码问题defbroken_line_chart(x,y1,y2):# 折线图绘制函数plt.figure(dpi500,figsize(10,5))plt.title(泸州-成都每日平均气温折线图)plt.plot(x,y1,colorcyan,label泸州)plt.plot(x,y2,coloryellow,label成都)# 获取图的坐标信息coordinatesplt.gca()# 设置x轴每个刻度的间隔天数xLocatormpl.ticker.MultipleLocator(30)coordinates.xaxis.set_major_locator(xLocator)# 将日期旋转30°plt.xticks(rotation30)plt.xticks(fontsize8)plt.ylabel(温度(℃))plt.xlabel(日期)plt.legend()plt.savefig(平均气温走势折线图.png)# 平均气温折线图plt.show()plt.close()data_luZhoupd.read_csv(C:\\Users\\Administrator\\Desktop\\泸州.csv)data_chengdupd.read_csv(C:\\Users\\Administrator\\Desktop\\成都.csv)# 将列的名称转为列表类型方便添加columSdata_luZhou.columns.tolist()columYdata_chengdu.columns.tolist()# 将数据转换为列表data_luZhounp.array(data_luZhou).tolist()data_chengdunp.array(data_chengdu).tolist()# 在最开始的位置上添加列的名字data_luZhou.insert(0,columS)data_chengdu.insert(0,columY)# 添加平均气温列data_luZhou[0].append(平均气温)data_chengdu[0].append(平均气温)weather_dict_luZhou{}weather_dict_chengdu{}foriinrange(1,len(data_luZhou)):# 去除日期中的星期data_luZhou[i][0]data_luZhou[i][0][0:10]data_chengdu[i][0]data_chengdu[i][0][0:10]# 获取平均气温average_luZhouint((int(data_luZhou[i][1])int(data_luZhou[i][2]))/2)average_chengduint((int(data_chengdu[i][1])int(data_chengdu[i][2]))/2)# 将平均气温添加进入列表中data_luZhou[i].append(average_luZhou)data_chengdu[i].append(average_chengdu)# 将新的数据存入新的csv中new_data_luZhoupd.DataFrame(columnsdata_luZhou[0],datadata_luZhou[1:])new_data_chengdupd.DataFrame(columnsdata_chengdu[0],datadata_chengdu[1:])new_data_luZhou.to_csv(泸州.csv,indexFalse,sep,)new_data_chengdu.to_csv(成都.csv,indexFalse,sep,)# 折线图的绘制y1np.array(new_data_luZhou.get(平均气温)).tolist()y2np.array(new_data_chengdu.get(平均气温)).tolist()xnp.array(new_data_luZhou.get(日期)).tolist()broken_line_chart(x,y1,y2)# 进行每个月的平均气温求解new_data_luZhou[日期]pd.to_datetime(new_data_luZhou[日期])new_data_chengdu[日期]pd.to_datetime(new_data_chengdu[日期])new_data_luZhou.set_index(日期,inplaceTrue)new_data_chengdu.set_index(日期,inplaceTrue)# 按月进行平均气温的求取new_data_luZhou[平均气温](new_data_luZhou[最高气温]new_data_luZhou[最低气温])/2new_data_chengdu[平均气温](new_data_chengdu[最高气温]new_data_chengdu[最低气温])/2month_lnew_data_luZhou[[平均气温]].resample(ME).mean()month_lnp.array(month_l).tolist()month_cnew_data_chengdu[[平均气温]].resample(ME).mean()month_cnp.array(month_c).tolist()lengthmin(len(month_c),len(month_l))month_average_l[]month_average_c[]foriinrange(length):month_average_l.append(month_l[i][0])month_average_c.append(month_c[i][0])month_list[str(i)月foriinrange(1,13)]plt.figure(dpi500,figsize(10,5))plt.title(泸州-成都每月平均折线气温图)plt.plot(month_list,month_average_l,colorcyan,label泸州,markero)plt.plot(month_list,month_average_c,colorblue,label成都,markerv)fora,binzip(month_list,month_average_l):plt.text(a,b0.5,%.2f%b,horizontalalignmentcenter,verticalalignmentbottom,fontsize6)fora,binzip(month_list,month_average_c):plt.text(a,b-0.5,%.2f%b,horizontalalignmentcenter,verticalalignmentbottom,fontsize6)plt.legend()plt.xlabel(月份)plt.ylabel(温度℃)plt.savefig(月平均气温折线图.png)# 月平均气温折线图plt.show()## 只获取两列的数据data_lpd.read_csv(泸州.csv,usecols[风向,平均气温])data_cpd.read_csv(成都.csv,usecols[风向,平均气温])data_lnp.array(data_l).tolist()data_cnp.array(data_c).tolist()day_c0day_l0foriinrange(len(data_l)):iflen(data_l[i][0])6:ifint(data_l[i][0][4])5and18int(data_l[i][1])25:day_l1else:ifint(data_l[i][0][3])5and18int(data_l[i][1])25:day_l1iflen(data_c[i][0])6:ifint(data_c[i][0][4])5and10int(data_c[i][1])25:day_c1else:ifint(data_c[i][0][3])5and18int(data_c[i][1])25:day_c1plt.figure(dpi500,figsize(8,4))plt.title(泸州-成都平均气温在18-25且风力5级的天数)list_name[泸州,成都]list_days[day_l,day_c]plt.bar(list_name,list_days,width0.5)plt.text(0,day_l,%.0f%day_l,horizontalalignmentcenter,verticalalignmentbottom,fontsize7)plt.text(1,day_c,%.0f%day_c,horizontalalignmentcenter,verticalalignmentbottom,fontsize7)plt.xlabel(城市)plt.ylabel(天数(d))plt.savefig(适宜居住柱形图.png)plt.show()data_lpd.read_csv(泸州.csv)data_cpd.read_csv(成都.csv)# 将数据转换为列表data_lnp.array(data_l).tolist()data_cnp.array(data_c).tolist()# 获取每种天气的天数采用字典类型进行存储foriinrange(1,min(len(data_l),len(data_c))):weather_ldata_l[i][3]weather_cdata_c[i][3]ifweather_linweather_dict_luZhou:weather_dict_luZhou[weather_l]weather_dict_luZhou.get(weather_l)1else:weather_dict_luZhou[weather_l]1ifweather_cinweather_dict_chengdu:weather_dict_chengdu[weather_c]weather_dict_chengdu.get(weather_c)1else:weather_dict_chengdu[weather_c]1weather_list_luZhoulist(weather_dict_luZhou)weather_list_chengdulist(weather_dict_chengdu)value_l[]value_c[]# 获取所有的天气种类weather_listsorted(set(weather_list_luZhouweather_list_chengdu))# 获取每种天气的天数并将其对应的放入列表中没有的则用0进行替代方便条形图的绘制。foriinweather_list:ifiinweather_dict_luZhou:value_l.append(weather_dict_luZhou[i])else:value_l.append(0)ifiinweather_dict_chengdu:value_c.append(weather_dict_chengdu[i])else:value_c.append(0)# 绘制条形图进行对比plt.figure(dpi500,figsize(10,5))plt.title(泸州-成都各种天气情况对比)x1list(range(len(weather_list)))x[i0.4foriinx1]plt.bar(x1,value_l,width0.4,colorred,label泸州)plt.bar(x,value_c,width0.4,colororange,label成都)fora,binzip(x1,value_l):plt.text(a,b0.4,%.0f%b,hacenter,vabottom,fontsize7)fora,binzip(x,value_c):plt.text(a,b0.4,%.0f%b,hacenter,vabottom,fontsize7)plt.xticks(x1,weather_list)plt.ylabel(天数)plt.xlabel(天气)plt.xticks(rotation270)plt.legend()plt.savefig(泸州成都天气情况对比.png)plt.show()plt.close()注意文件保存路径该成你们自己的哦ok,爬取代码就到这接下来是图形化效果大致如下

更多文章