Python爬虫+数据分析实战--爬取并分析中国天气网的温度信息
程序员文章站
2022-07-14 17:35:46
...
Python爬虫+数据分析实战–爬取并分析中国天气网的温度信息
一、使用的工具
单独使用完成 pycharms 完成实验,在分析的时候使用 Jupyter Notebook
在爬虫所需要lxml和bs4这两个库已经确认安装后,确保自己的已经安装了pandas和matplotlib这两个库
1.安装方式:
# 推荐使用清华镜像下载速度较快
pip install pandas -i https://pypi.tuna.tsinghua.edu.cn/simple
pip install matplotlib -i https://pypi.tuna.tsinghua.edu.cn/simple
2.简介
Pandas | 可以对数据进行导入、清洗、处理、统计和输出 |
---|---|
Matplotlib | 能够生成各种格式的图形(诸如折线图,散点图,直方图等等),界面可交互 |
二、基本思路
1.目的
爬取中国天气网的温度数据
画出温度最高前10名的数据展示图
画出温度最低前10名的数据展示图
2.步骤
2.1 爬取数据
分析网址
满足http://www.weather.com.cn/textFC/{}.shtml的格式
定位于东北的网址:http://www.weather.com.cn/textFC/db.shtml
定位于华北的网址:http://www.weather.com.cn/textFC/hb.shtml
定位于华中的网址:http://www.weather.com.cn/textFC/hz.shtml
zone = ['db', 'hb', 'hd', 'hz', 'hn', 'xb', 'xn', 'gat']
for z in zone:
url = "http://www.weather.com.cn/textFC/{}.shtml".format(z)
爬取数据
使用bs4库来爬取中国天气网的最高气温,存储到一个列表HIGH_DATA中
具体分析可以看小编之前的数据分析的三种方法,在文章后面附加链接
HIGH_DATA = []
response = requests.get(url, headers=headers)
text = response.content.decode("utf-8")
soup = BeautifulSoup(text,'html5lib')
conMidtab = soup.find('div',class_='conMidtab')
tables = conMidtab.find_all('table')
for table in tables:
trs = table.find_all('tr')[2:]
for index,tr in enumerate(trs): # ebumerate能够取出对应的下标和值
tds = tr.find_all('td')
if index == 0:
city_td = tds[1]
else:
city_td = tds[0]
city = list(city_td.stripped_strings)[0]
temp_td = tds[-5]
max_temp = list(temp_td.stripped_strings)[0]
HIGH_DATA.append({"city": city, 'high_temp': int(max_temp)})
使用lxml库来爬取中国天气网的最低气温数据,存储到一个列表LOW_DATA中
response = requests.get(url, headers=headers)
text = response.text.encode('ISO-8859-1')
trees = etree.HTML(text)
citys = trees.xpath('//div[@class="hanml"]/div[1]//td[@width="83"][@height="23"]/a/text()')
lows = trees.xpath('//div[@class="hanml"]/div[1]//td[@width="86"]/text()')
while True:
if '最低气温' not in lows:
break
else:
lows.remove('最低气温')
for i in zip(citys, lows):
city, low = i
LOW_DATA.append({"city": city, "low_temp": int(low)})
2.2 数据清洗
使用pandas的DataFrame对象来获取前十名的数据
# 将取出的数据转为DataFrame对象,相当于一个表格
i = pd.DataFrame(LOW_DATA)
j = pd.DataFrame(HIGH_DATA)
# 经过排序来取出前十名的数据,分别放在ten_low和ten_high中
ten_low = i.sort_values(by="low_temp", ascending=True)[0:10]
ten_high = j.sort_values(by="high_temp", ascending=True)[-10:]
2.3 绘制图形
使用Matplotlib来绘制图案,需要解决的问题为文本显示问题还有符号显示问题
具体的方法在代码都已经说明
# 分区域绘图subplot(行,列,第()个)
plt.subplot(2, 1, 1)
# 逆序排序取前面十个然后放在ten_low中
ten_low = i.sort_values(by="low_temp", ascending=True)[0:10]
# 设置x和y轴的字体为黑体(SimHei)/解决轴不能显示字体的问题
plt.rcParams['font.sans-serif'] = ['SimHei']
# 解决不能显示负号的问题
plt.rcParams['axes.unicode_minus'] = False
# 取出ten_low中的城市和气温
x1 = list(ten_low['city'])
y1 = list(ten_low['low_temp'])
# 画出bar图
plt.bar(x1, y1)
# 定义x和y轴的名称
plt.xlabel('城市', fontproperties='SimHei')
plt.ylabel("温度", fontproperties='SimHei')
# 定义图表的名称
plt.title("中国各个城市的今日温度最低前十名", fontproperties='SimHei')
# 显示bar图上的数值
for x, y in zip(x1, y1):
plt.text(x, y, '%s' % y, ha='center', va='bottom')
# 画出第二个子图
plt.subplot(2, 1, 2)
# 取出最低气温的后面十个数值
ten_high = j.sort_values(by="high_temp", ascending=True)[-10:]
x2 = list(ten_high['city'])
y2 = list(ten_high['high_temp'])
# plt.rcParams['font.sans-serif'] = ['SimHei']
# plt.rcParams['axes.unicode_minus'] = False
plt.bar(x2, y2)
plt.xlabel('城市', fontproperties='SimHei')
plt.ylabel("温度", fontproperties='SimHei')
plt.title("中国各个城市的今日温度最高前十名", fontproperties='SimHei')
for x, y in zip(x2, y2):
plt.text(x, y, '%s' % y, ha='center', va='bottom')
# 调整每隔子图之间的距离(默认)
plt.tight_layout()
plt.show()
2.3 实验结果
注:5月25日的数据(以实战当天为准)
三、源代码
用函数进行封装
import requests
import pandas as pd
from bs4 import BeautifulSoup
from fake_useragent import UserAgent
from lxml import etree
import matplotlib.pyplot as plt
'''
爬取中国天气网的温度数据并汇总
画出温度最高前10名的数据展示图
画出温度最低前10名的数据展示图
'''
headers = {
"user-agent": UserAgent().random
}
HIGH_DATA = []
LOW_DATA = []
# 使用bs4库的BeautifSoup对象来获取最高温度的数据,使用HIGH_DATA来存放数据
def get_high_temperature(url):
response = requests.get(url, headers=headers)
text = response.content.decode("utf-8")
soup = BeautifulSoup(text,'html5lib')
conMidtab = soup.find('div',class_='conMidtab')
tables = conMidtab.find_all('table')
for table in tables:
trs = table.find_all('tr')[2:]
for index,tr in enumerate(trs): # ebumerate能够取出对应的下标和值
tds = tr.find_all('td')
if index == 0:
city_td = tds[1]
else:
city_td = tds[0]
city = list(city_td.stripped_strings)[0]
temp_td = tds[-5]
max_temp = list(temp_td.stripped_strings)[0]
HIGH_DATA.append({"city": city, 'high_temp': int(max_temp)})
# 使用lxml库的xpath方法来获取最低温度的数据,使用LOW_DATA来存储数据
def get_low_temperature(url):
response = requests.get(url, headers=headers)
text = response.text.encode('ISO-8859-1')
trees = etree.HTML(text)
citys = trees.xpath('//div[@class="hanml"]/div[1]//td[@width="83"][@height="23"]/a/text()')
lows = trees.xpath('//div[@class="hanml"]/div[1]//td[@width="86"]/text()')
while True:
if '最低气温' not in lows:
break
else:
lows.remove('最低气温')
for i in zip(citys, lows):
city, low = i
LOW_DATA.append({"city": city, "low_temp": int(low)})
# 使用pandas来格式化数据,使用matplotlib.pyplot 画图
def draw_picture(LOW,HIGH):
i = pd.DataFrame(LOW)
j = pd.DataFrame(HIGH)
# 分区域绘图subplot(行,列,第()个)
plt.subplot(2, 1, 1)
# 逆序排序取前面十个然后放在ten_low中
ten_low = i.sort_values(by="low_temp", ascending=True)[0:10]
# 设置x和y轴的字体为黑体(SimHei)/解决轴不能显示字体的问题
plt.rcParams['font.sans-serif'] = ['SimHei']
# 解决不能显示负号的问题
plt.rcParams['axes.unicode_minus'] = False
# 取出ten_low中的城市和气温
x1 = list(ten_low['city'])
y1 = list(ten_low['low_temp'])
# 画出bar图
plt.bar(x1, y1)
# 定义x和y轴的名称
plt.xlabel('城市', fontproperties='SimHei')
plt.ylabel("温度", fontproperties='SimHei')
# 定义图表的名称
plt.title("中国各个城市的今日温度最低前十名", fontproperties='SimHei')
# 显示bar图上的数值
for x, y in zip(x1, y1):
plt.text(x, y, '%s' % y, ha='center', va='bottom')
# 画出第二个子图
plt.subplot(2, 1, 2)
# 取出最低气温的后面十个数值
ten_high = j.sort_values(by="high_temp", ascending=True)[-10:]
x2 = list(ten_high['city'])
y2 = list(ten_high['high_temp'])
# plt.rcParams['font.sans-serif'] = ['SimHei']
# plt.rcParams['axes.unicode_minus'] = False
plt.bar(x2, y2)
plt.xlabel('城市', fontproperties='SimHei')
plt.ylabel("温度", fontproperties='SimHei')
plt.title("中国各个城市的今日温度最高前十名", fontproperties='SimHei')
for x, y in zip(x2, y2):
plt.text(x, y, '%s' % y, ha='center', va='bottom')
# 调整每隔子图之间的距离(默认)
plt.tight_layout()
plt.show()
def main():
zone = ['db', 'hb', 'hd', 'hz', 'hn', 'xb', 'xn', 'gat']
for z in zone:
url = "http://www.weather.com.cn/textFC/{}.shtml".format(z)
get_high_temperature(url)
get_low_temperature(url)
draw_picture(LOW_DATA,HIGH_DATA)
if __name__ == '__main__':
main()
写在最后
在实战出现l什么问题可以随时留言告诉小编,另外附加一个bug,在每天晚上中国天气网当天的最高气温可能会发生变化,数据会被清除变成‘-’,导致实验失败,注意自己的实战时间
爬虫的爬取方法:https://blog.csdn.net/weixin_45127640/article/details/106120189
数据分析推荐学习:https://blog.csdn.net/weixin_44888486/article/details/103272520