import requests
from bs4 import BeautifulSoup
from pandas import read_csv
from IPython.display import display
import pandas as pd
# 这段代码是为了在pycharm的控制台中显示全部,不需要的可以不加
# 设置控制台输出结果的可显示长度
pd.set_option('display.max_columns', 1000)
pd.set_option('display.width', 1000)
pd.set_option('display.max_colwidth', 1000)
# 设置控制台输出结果的对齐
pd.set_option('display.unicode.ambiguous_as_wide', True)
pd.set_option('display.unicode.east_asian_width', True)
# 爬虫 天气信息&空气质量数据 http://www.tianqihoubao.com/
def AQI_data(city, *years):
m = ['01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12'] # 月份
urls = []
for year in range(years[0], years[-1] + 1):
for m1 in m:
ur = 'http://www.tianqihoubao.com/aqi/%s-%d'%(city,year) + m1 + '.html'
urls.append(ur) # 循环得出所有爬取网址
file = open('AQI_data.csv', 'w', encoding='UTF-8') # 设置编码方式 进行写操作
header = {'User-Agent':
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36'} # 设置用户代理
for url in urls:
response = requests.get(url, headers = header) # 配置信息
soup = BeautifulSoup(response.text, 'html.parser') # 获取网页代码
weather_list = soup.select('div[class="api_month_list"]') # 选择特定div
for weather in weather_list:
weather_date = weather.select('table[class="b"]') # 选择div中特定table
ul_list = weather.select('tr') # 选择table中所有tr
for ul in ul_list: # 循环每次得到一个tr
li_list = ul.select('td') # 选择tr中所有td
str = ""
for li in li_list: # 循环每次得到一个td
l = li.string # list转换string
print(l)
if (l == None):
str = str + '无数据' + ',' # 空值用‘无数据’填充
else:
str = str + l.strip() + ',' # 清除数据中的空格
if (str != ' '):
file.write(str + '\n') # 写数据+换行
file.close()
# 爬虫def运行,城市和时间可以自由改变
AQI_data('dalian',2017,2020)
# 导入数据
aqi = read_csv('AQI_data.csv', encoding='UTF-8', header=None)
display(aqi.head(n=5)) # 显示前5行
# 数据清洗
del aqi[8] # 删除多余列
del aqi[9]
del aqi[10]
aqi.columns = ['日期', '质量等级', 'AQI指数', 'AQI排名', 'PM2.5', 'PM10', 'So2', 'No2'] # 设置列索引
aqi = aqi[~aqi['日期'].isin(['无数据'])] # 选取aqi中日期列不包含'无数据'的行
aqi = aqi.drop_duplicates() # 删除重复值
aqi = aqi.astype({'AQI指数':'int', 'AQI排名':'int', 'PM2.5':'int', 'PM10':'int', 'So2':'int', 'No2':'int'}) # 将需要的列从str类型转换为int类型
display(aqi.head(n=5)) # 显示前5行