####分市爬取数据部分
from pypinyin import lazy_pinyin, Style
import requests
from lxml import etree
import pandas as pd
import time
def get_html(dq,month):
# print(dq,month)
headers = {
"Accept-Encoding": "Gzip",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36",
}
url = 'https://lishi.tianqi.com/{0}/{1}.html'.format(dq,month)
# print(url)
r = requests.get(url, headers=headers)
r_html = etree.HTML(r.text)
return r_html
# 月份参数列表,这里需要修改时间区间的可以修改range中的数据
month_list = pd.period_range('201506','202202',freq='M').strftime('%Y%m')
print(month_list)
DQ=['西安','咸阳','宝鸡','渭南','铜川','延安','榆林','汉中','安康','商洛']
# DQ=['西安']
# https://lishi.tianqi.com/xian/201506.html
# df = pd.DataFrame(columns=['日期', '最高气温', '最低气温', '天气', '风向','地区'])
for dq in DQ:
newdq= Ename=''.join(lazy_pinyin(dq))
df = pd.DataFrame(columns=['日期', '最高气温', '最低气温', '天气', '风向','地区'])
for i ,month in enumerate(month_list):
# print(newdq,month)
time.sleep(5)
r_html = get_html(newdq,month)
# 找到存放历史天气数据的div节点
div = r_html.xpath('.//div[@class="tian_three"]')[0]
# 每个日期的历史天气数据的li节点组成的列表
lis = div.xpath('.//li')
for li in lis:
item = {
'日期':li.xpath('./div[@class="th200"]/text()')[0],
'最高气温':li.xpath('./div[@class="th140"]/text()')[0],
'最低气温':li.xpath('./div[@class="th140"]/text()')[1],
'天气':li.xpath('./div[@class="th140"]/text()')[2],
'风向':li.xpath('./div[@class="th140"]/text()')[3]
}
df = df.append(item, ignore_index=True)
print(df)
print(f'{i+1}个月数据已采集')
df['地区']=dq
df.to_excel('{0}十年历史天气数据.xlsx'.format(dq),index=False)
time.sleep(5)###睡眠时间可以更长
# df.to_excel(r'北京历史天气数据2020.xlsx',index=None)
爬完数据后进行分析和可视化
合并数据
import os
import glob
import pandas as pd
import warnings
warnings.filterwarnings("ignore")
data_path = r"D:\数据\数据挖掘机器学习\练习作业\20220307\天气数据"
####合并数据为一个整体的文件
os.chdir(data_path)
retval = os.getcwd()
# print(retval)
aa='xlsx' #后缀为xlsx格式的文件
a=[i for i in glob.glob('*.{}'.format(aa))] #加载所有后缀为csv的文件。
weather = pd.concat([pd.read_excel(i) for i in a]) #合并
weather=weather.reset_index()
# b.to_excel( "天气数据.xlsx", index=False, encoding='utf-8-sig') #存档
weather=weather.drop(columns='index')####删除没用的列
###将日期中的时间和星期分开
weather['星期']=weather['日期'].str.split(' ').str[1]
weather['时间']=weather['日期'].str.split(' ').str[0]
weather['时间'] = pd.to_datetime(weather['时间'])
#将上一行数据填充到空值处
weather['天气'].fillna(method = 'pad',inplace = True)
#去除气温中的字符
weather[['最高气温','最低气温']] = weather[['最高气温','最低气温']].apply(lambda x: x.str.replace('℃',''))
####将气温数字转化成数字类型
weather[['最高气温','最低气温']] = weather[['最高气温','最低气温']].astype('int')
weather['年份'] = weather['时间'].dt.year
weather['月份'] = weather['时间'].dt.month
weather['日'] = weather['时间'].dt.day
# 预览
weather.sample(5)
weather['日期']=weather['时间']
####查看天气是否下雪
weather.loc[weather['天气'].str.contains('雪'),'下雪吗']='是'
weather.fillna('否',inplace=True)
#各城市初雪的时间
s_weather = weather[weather['下雪吗']=='是']
s_weather[(s_weather['月份']>=9)].groupby('年份').first().reset_index()
#各城市下雪天雪天数
snowdata=s_weather.groupby(['地区','年份'])['时间'].count().to_frame('下雪天数').reset_index()
import matplotlib.pyplot as plt
import matplotlib.colors as mcolors
import seaborn as sns
# 设置全局默认字体 为 雅黑
plt.rcParams['font.family'] = ['Microsoft YaHei']
# 设置全局轴标签字典大小
plt.rcParams["axes.labelsize"] = 14
# 设置背景
sns.set_style("darkgrid", {"font.family": ['Microsoft YaHei', 'SimHei']})
# 设置画布长宽和 dpi
plt.figure(figsize=(16, 8), dpi=100)
# 自定义色卡
cmap = mcolors.LinearSegmentedColormap.from_list(
"n", ['#95B359', '#D3CF63', '#E0991D', '#D96161', '#A257D0', '#7B1216'])
plt.figure(figsize=(10,8))
# 用seaborn制图(可增加图例、最高温度):
ax = sns.heatmap(data_pivot, # 指定绘图数据
cmap=cmap, # 指定填充色
# center=300,
linewidths=0.05, # 设置每个单元方块的间隔
annot=True, # 显示数值
robust=True,
)
ax.set_xlabel('')
ax.xaxis.set_ticks_position('top')
# ax.set_xticklabels([]) #设置x轴图例为空值
plt.title('西安2021年天气分布热力图',fontsize=20)
plt.show()
import matplotlib.pyplot as plt
import matplotlib.colors as mcolors
import seaborn as sns
import numpy as np
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus'] = False
x = np.arange(len(labels)) # the label locations
width = 0.25 # the width of the bars
fig, ax = plt.subplots(dpi=128,figsize=(6,3.6))
rects1 = ax.bar(x - width, results['扬沙'], width, label='扬沙',color='orange')
rects2 = ax.bar(x , results['浮尘'], width, label='浮尘',color='#BA55D3')
rects3 = ax.bar(x + width, results['霾'], width, label='霾',color='#40E0D0')
ax.set_ylabel('Days')
ax.set_title('陕西10年天气数据')
ax.set_xticks(x,labels)
# ax.set_xticklabels(labels)
ax.legend(frameon=False) # 不显示图例边框
ax.bar_label(rects1, padding=3)
ax.bar_label(rects2, padding=3)
ax.bar_label(rects3, padding=3)
plt.ylim(0,210)
fig.tight_layout()# 自动调整子图参数,使之填充整个图像区域。
plt.show()
plt.savefig('天气数据.png')