一.设计方案
爬虫名称:爬取天气情况并进行可视化
爬虫内容:爬取2020年3月份莆田市天气情况
爬虫设计:目标url,获取网页源代码,数据提取,数据保存
二.页面的结构特征分析(网址:http://www.tianqihoubao.com/lishi/putian/month/202003.html)
结构特质分析:源文件为html结构
页面解析以及节点查找
找到节点为<table width="100%" class="b" border="0" cellspacing="1" cellpadding="1">
三.爬虫程序
数据爬取与采集
import requests
from bs4 import BeautifulSoup
#目标url
url = 'http://www.tianqihoubao.com/lishi/putian/month/202003.html'
#获取网页源代码
resp = requests.get(url)
html = resp.content.decode('gbk')
#数据提取
soup = BeautifulSoup(html,'html.parser')
tr_list = soup.find_all('tr')
print(tr_list)
结果如图(部分截取)
数据处理
dates,conditions,temp = [],[],[]
for data in tr_list[1:]:
sub_data = data.text.split()
dates.append(sub_data[0])
conditions.append(''.join(sub_data[1:3]))
temp.append(''.join(sub_data[3:6]))
_data = pd.DataFrame()
_data['日期'] = dates
_data['天气情况'] = conditions
_data['气温'] = temp
print(_data)
结果如图
数据可视化
#数据可视化
from matplotlib import pyplot as plt
#显示中文
plt.rcParams['font.sans-serif'] = ['SimHei']
#显示负号
plt.rcParams['axes.unicode_minus'] = False
data = pd.read_csv('putian.csv')
#数据处理
data['最高气温'] = data['气温'].str.split('/',expand=True)[0]
data['最低气温'] = data['气温'].str.split('/',expand=True)[1]
data['最高气温'] = data['最高气温'].map(lambda x:int(x.replace('℃','')))
data['最低气温'] = data['最低气温'].map(lambda x:int(x.replace('℃','')))
dates = data['日期']
highs = data['最高气温']
lows = data['最低气温']
#画图
fig = plt.figure(dpi=128,figsize=(10,6))
plt.plot(dates,highs, c='red',alpha=0.5)
plt.plot(dates,lows, c='blue',alpha=0.5)
plt.fill_between(dates,highs,lows,facecolor='blue',alpha=0.2)
#图表格式
#设置图形格式
plt.title('2020年三月份天气',fontsize=24)
plt.xlabel('',fontsize=6)
fig.autofmt_xdate() #绘制斜的日期标签,避免重叠
plt.ylabel('气温',fontsize=12)
plt.tick_params(axis='both',which='major',labelsize=10)
#修改刻度
plt.xticks(dates[::1])
#显示折线图
plt.show()
结果如图
最高气温与最低气温的相关系数及两者的散点图与回归方程
相关系数
#绘制散点图以及回归方程
#计算相关系数
X = highs
Y = lows
X.corr(Y)
结果如图
散点图
#散点图
plt.title('2020年三月份最高温与最低温散点图',fontsize=20)
x = highs
y = lows
plt.xlabel('最高温度',fontsize=12)
plt.ylabel('最低温度',fontsize=12)
plt.scatter(x,y,color='purple',linewidth=2)
plt.show()
结果如图
回归方程
#回归方程
import numpy as np
from scipy.optimize import leastsq
X = np.array(highs)
Y = np.array(lows)
def func(params, x):
k, b = params
return k*x+b
def error(params,x,y):
return func(params,x) - y
def main():
plt.figure(figsize=(10,6))
p0 = [0,0]
Para = leastsq(error, p0, args=(X,Y))
k, b = Para[0]
print("k={:.2f},b={:.2f}".format(k,b))
plt.scatter(X,Y,color='green',label='样本数据',linewidth=2)
#画拟合曲线
x = np.linspace(1,30,30)
y = k*x+b
plt.plot(x,y,color='red',label='拟合曲线',linewidth=2)
plt.title('2020年三月分最低温与最高温光系图')
plt.grid()
plt.legend()
plt.show()
main()
结果如图
数据持久化
fig = plt.gcf()
plt.show()
fig.savefig('putian.png', dpi=100)
结果如图
整理后的完整代码
1 import requests
2 import pandas as pd
3 from bs4 import BeautifulSoup
4 #目标url
5 url = 'http://www.tianqihoubao.com/lishi/putian/month/202003.html'
6 #获取网页源代码
7 resp = requests.get(url)
8 html = resp.content.decode('gbk')
9 #数据提取
10 soup = BeautifulSoup(html,'html.parser')
11 tr_list = soup.find_all('tr')
12
13 dates,conditions,temp = [],[],[]
14 for data in tr_list[1:]:
15 sub_data = data.text.split()
16 dates.append(sub_data[0])
17 conditions.append(''.join(sub_data[1:3]))
18 temp.append(''.join(sub_data[3:6]))
19 _data = pd.DataFrame()
20 _data['日期'] = dates
21 _data['天气情况'] = conditions
22 _data['气温'] = temp
23 _data.to_csv('putian.csv',index=False,encoding='utf-8')#去掉索引以及避免乱码
24
25 #数据可视化
26 from matplotlib import pyplot as plt
27 #显示中文
28 plt.rcParams['font.sans-serif'] = ['SimHei']
29 #显示负号
30 plt.rcParams['axes.unicode_minus'] = False
31 data = pd.read_csv('putian.csv')
32 #数据处理
33 data['最高气温'] = data['气温'].str.split('/',expand=True)[0]
34 data['最低气温'] = data['气温'].str.split('/',expand=True)[1]
35 data['最高气温'] = data['最高气温'].map(lambda x:int(x.replace('℃','')))
36 data['最低气温'] = data['最低气温'].map(lambda x:int(x.replace('℃','')))
37
38 dates = data['日期']
39 highs = data['最高气温']
40 lows = data['最低气温']
41
42 #画图
43 fig = plt.figure(dpi=128,figsize=(10,6))
44
45 plt.plot(dates,highs, c='red',alpha=0.5)
46 plt.plot(dates,lows, c='blue',alpha=0.5)
47
48 plt.fill_between(dates,highs,lows,facecolor='blue',alpha=0.2)
49
50 #图表格式
51 #设置图形格式
52 plt.title('2020年三月份天气',fontsize=24)
53 plt.xlabel('',fontsize=6)
54 fig.autofmt_xdate() #绘制斜的日期标签,避免重叠
55 plt.ylabel('气温',fontsize=12)
56 plt.tick_params(axis='both',which='major',labelsize=10)
57
58 #修改刻度
59 plt.xticks(dates[::1])
60
61 #显示折线图
62 plt.show()
63
64 #绘制散点图以及回归方程
65 #计算相关系数
66 x = highs
67 y = lows
68 x.corr(y)
69
70 #散点图
71 plt.title('2020年三月份最高温与最低温散点图',fontsize=20)
72 x = highs
73 y = lows
74 plt.xlabel('最高温度',fontsize=12)
75 plt.ylabel('最低温度',fontsize=12)
76 plt.scatter(x,y,color='purple',linewidth=2)
77 plt.show()
78
79 #回归方程
80 import numpy as np
81 from scipy.optimize import leastsq
82 X = np.array(highs)
83 Y = np.array(lows)
84 def func(params, x):
85 k, b = params
86 return k*x+b
87 def error(params,x,y):
88 return func(params,x) - y
89 def main():
90 plt.figure(figsize=(10,6))
91 p0 = [0,0]
92 Para = leastsq(error, p0, args=(X,Y))
93 k, b = Para[0]
94 print("k={:.2f},b={:.2f}".format(k,b))
95 plt.scatter(X,Y,color='green',label='样本数据',linewidth=2)
96 #画拟合曲线
97 x = np.linspace(1,30,30)
98 y = k*x+b
99 plt.plot(x,y,color='red',label='拟合曲线',linewidth=2)
100 plt.title('2020年三月分最低温与最高温光系图')
101 plt.grid()
102 plt.legend()
103 plt.show()
104 main()
105
106 #数据持久化
107 fig = plt.gcf()
108 plt.show()
109 fig.savefig('putian.png', dpi=100)
完整运行结果如图
四.结论
1.2020年3月份莆田每日温差较大,且呈现出逐渐上升趋势,每日最高温度与最低温度相关性也较大,且进行数据可视化后可以更为直观明了的观察,而三月份最低温度也在10摄氏度左右,可以看出是一个很适合居住的城市。
2.本次程序设计任务,我选择的是爬取天气后报网,课题是爬取3月份的天气情况,并不是天气预报,对于这个网址的爬取相对简单,首先它是一个静态网页,其次节点也相当好找,而且爬虫部分也不需要伪装,可以说是一个相对简单的课题。但是不可否认的是,在程序设计过程中出现了较多问题,如基础不扎实,一部分报错无法看懂,在数据处理时将列表改为整形数据时遇到了困难,进行了大量尝试才最终成功,又如在数据可视化过程中遇到了纵坐标数据出现乱序,而找不出原因,又进行了大量的尝试,再如最后阶段的数据持久化,初看认为很简单,却也让我大费脑筋,更让我认识的自己的基本功之不扎实,但相较于上一次作业而言,完成度相对较高,基本完成了任务目标。
以上。