Python天气查询系统(连接数据库版)
?作為一名大三的準程序員,這學期學了一門叫做腳本程序設計的課程,剛好很感興趣,于是做了一個相關(guān)的爬蟲系統(tǒng),目前只能算是半成品,因為還想到了很多可以跟進的地方,但奈何知識儲備不夠,所以先發(fā)布一下目前的版本。
我爬取的是中國氣象網(wǎng)的天氣預報
成都天氣預報,成都7天天氣預報,成都15天天氣預報,成都天氣查詢
下面我一 一講解一下我寫的代碼
目錄
觀察連接
判斷城市是否存在?
獲取url
請求獲取網(wǎng)頁內(nèi)容
處理信息
保存csv
創(chuàng)建數(shù)據(jù)庫表單
存儲數(shù)據(jù)到數(shù)據(jù)庫
繪制當天溫度曲線
繪制15天溫度曲線
相對濕度曲線繪制
空氣質(zhì)量曲線繪制
風向雷達圖繪制
繪制天氣餅圖
main主函數(shù)
全部代碼展示
觀察連接
首先,我們要先觀察這個連接,他有什么獨特之處。成都天氣預報,成都7天天氣預報,成都15天天氣預報,成都天氣查詢
通過觀察,我們發(fā)現(xiàn)了兩個獨特之處。
首先,就是weather1d,我在這里給大家解釋一下,其中的‘1d’代表當天的天氣情況,之后還會用到‘15d’,它代表的便是未來14天的天氣情況
然后就是101270101這串數(shù)字編碼,這其實是成都的城市編碼,我當時看了一下中國氣象網(wǎng)的源文件,并沒有找到所以城市的編碼,無奈只好問問度娘,下面我把城市編碼放上來
北京:101010100都江堰:101270111朝陽:101010300順義:101010400懷柔:101010500通州:101010600昌平:101010700延慶:101010800豐臺:101010900石景山:101011000大興:101011100房山:101011200密云:101011300門頭溝:101011400平谷:101011500八達嶺:101011600佛爺頂:101011700湯河口:101011800密云上甸子:101011900齋堂:101012000霞云嶺:101012100北京城區(qū):101012200海淀:101010200天津:101030100寶坻:101030300東麗:101030400西青:101030500北辰:101030600薊縣:101031400漢沽:101030800靜海:101030900津南:101031000塘沽:101031100大港:101031200武清:101030200寧河:101030700上海:101020100寶山:101020300嘉定:101020500南匯:101020600浦東:101021300青浦:101020800松江:101020900奉賢:101021000崇明:101021100徐家匯:101021200閔行:101020200金山:101020700石家莊:101090101張家口:101090301承德:101090402唐山:101090501秦皇島:101091101滄州:101090701衡水:101090801邢臺:101090901邯鄲:101091001保定:101090201廊坊:101090601鄭州:101180101新鄉(xiāng):101180301許昌:101180401平頂山:101180501信陽:101180601南陽:101180701開封:101180801洛陽:101180901商丘:101181001焦作:101181101鶴壁:101181201濮陽:101181301周口:101181401漯河:101181501駐馬店:101181601三門峽:101181701濟源:101181801安陽:101180201合肥:101220101蕪湖:101220301淮南:101220401馬鞍山:101220501安慶:101220601宿州:101220701阜陽:101220801亳州:101220901黃山:101221001滁州:101221101淮北:101221201銅陵:101221301宣城:101221401六安:101221501巢湖:101221601池州:101221701蚌埠:101220201杭州:101210101舟山:101211101湖州:101210201嘉興:101210301金華:101210901紹興:101210501臺州:101210601溫州:101210701麗水:101210801衢州:101211001寧波:101210401重慶:101040100合川:101040300南川:101040400江津:101040500萬盛:101040600渝北:101040700北碚:101040800巴南:101040900長壽:101041000黔江:101041100萬州天城:101041200萬州龍寶:101041300涪陵:101041400開縣:101041500城口:101041600云陽:101041700巫溪:101041800奉節(jié):101041900巫山:101042000潼南:101042100墊江:101042200梁平:101042300忠縣:101042400石柱:101042500大足:101042600榮昌:101042700銅梁:101042800璧山:101042900豐都:101043000武隆:101043100彭水:101043200綦江:101043300酉陽:101043400秀山:101043600沙坪壩:101043700永川:101040200福州:101230101泉州:101230501漳州:101230601龍巖:101230701晉江:101230509南平:101230901廈門:101230201寧德:101230301莆田:101230401三明:101230801蘭州:101160101平?jīng)?101160301慶陽:101160401武威:101160501金昌:101160601嘉峪關(guān):101161401酒泉:101160801天水:101160901武都:101161001臨夏:101161101合作:101161201白銀:101161301定西:101160201張掖:101160701廣州:101280101惠州:101280301梅州:101280401汕頭:101280501深圳:101280601珠海:101280701佛山:101280800肇慶:101280901湛江:101281001江門:101281101河源:101281201清遠:101281301云浮:101281401潮州:101281501東莞:101281601中山:101281701陽江:101281801揭陽:101281901茂名:101282001汕尾:101282101韶關(guān):101280201南寧:101300101柳州:101300301來賓:101300401桂林:101300501梧州:101300601防城港:101301401貴港:101300801玉林:101300901百色:101301001欽州:101301101河池:101301201北海:101301301崇左:101300201賀州:101300701貴陽:101260101安順:101260301都勻:101260401興義:101260906銅仁:101260601畢節(jié):101260701六盤水:101260801遵義:101260201凱里:101260501昆明:101290101紅河:101290301文山:101290601玉溪:101290701楚雄:101290801普洱:101290901昭通:101291001臨滄:101291101怒江:101291201香格里拉:101291301麗江:101291401德宏:101291501景洪:101291601大理:101290201曲靖:101290401保山:101290501呼和浩特:101080101烏海:101080301集寧:101080401通遼:101080501阿拉善左旗:101081201鄂爾多斯:101080701臨河:101080801錫林浩特:101080901呼倫貝爾:101081000烏蘭浩特:101081101包頭:101080201赤峰:101080601南昌:101240101上饒:101240301撫州:101240401宜春:101240501鷹潭:101241101贛州:101240701景德鎮(zhèn):101240801萍鄉(xiāng):101240901新余:101241001九江:101240201吉安:101240601武漢:101200101黃岡:101200501荊州:101200801宜昌:101200901恩施:101201001十堰:101201101神農(nóng)架:101201201隨州:101201301荊門:101201401天門:101201501仙桃:101201601潛江:101201701襄樊:101200201鄂州:101200301孝感:101200401黃石:101200601咸寧:101200701成都:101270101自貢:101270301綿陽:101270401南充:101270501達州:101270601遂寧:101270701廣安:101270801巴中:101270901瀘州:101271001宜賓:101271101內(nèi)江:101271201資陽:101271301樂山:101271401眉山:101271501涼山:101271601雅安:101271701甘孜:101271801阿壩:101271901德陽:101272001廣元:101272101攀枝花:101270201銀川:101170101中衛(wèi):101170501固原:101170401石嘴山:101170201吳忠:101170301西寧:101150101黃南:101150301海北:101150801果洛:101150501玉樹:101150601海西:101150701海東:101150201海南:101150401濟南:101120101濰坊:101120601臨沂:101120901菏澤:101121001濱州:101121101東營:101121201威海:101121301棗莊:101121401日照:101121501萊蕪:101121601聊城:101121701青島:101120201淄博:101120301德州:101120401煙臺:101120501濟寧:101120701泰安:101120801西安:101110101延安:101110300榆林:101110401銅川:101111001商洛:101110601安康:101110701漢中:101110801寶雞:101110901咸陽:101110200渭南:101110501太原:101100101臨汾:101100701運城:101100801朔州:101100901忻州:101101001長治:101100501大同:101100201陽泉:101100301晉中:101100401晉城:101100601呂梁:101101100烏魯木齊:101130101石河子:101130301昌吉:101130401吐魯番:101130501庫爾勒:101130601阿拉爾:101130701阿克蘇:101130801喀什:101130901伊寧:101131001塔城:101131101哈密:101131201和田:101131301阿勒泰:101131401阿圖什:101131501博樂:101131601克拉瑪依:101130201拉薩:101140101山南:101140301阿里:101140701昌都:101140501那曲:101140601日喀則:101140201林芝:101140401臺北縣:101340101高雄:101340201臺中:101340401???101310101三亞:101310201東方:101310202臨高:101310203澄邁:101310204儋州:101310205昌江:101310206白沙:101310207瓊中:101310208定安:101310209屯昌:101310210瓊海:101310211文昌:101310212保亭:101310214萬寧:101310215陵水:101310216西沙:101310217南沙島:101310220樂東:101310221五指山:101310222瓊山:101310102長沙:101250101株洲:101250301衡陽:101250401郴州:101250501常德:101250601益陽:101250700婁底:101250801邵陽:101250901岳陽:101251001張家界:101251101懷化:101251201黔陽:101251301永州:101251401吉首:101251501湘潭:101250201南京:101190101鎮(zhèn)江:101190301蘇州:101190401南通:101190501揚州:101190601宿遷:101191301徐州:101190801淮安:101190901連云港:101191001常州:101191101泰州:101191201無錫:101190201鹽城:101190701哈爾濱:101050101牡丹江:101050301佳木斯:101050401綏化:101050501黑河:101050601雙鴨山:101051301伊春:101050801大慶:101050901七臺河:101051002雞西:101051101鶴崗:101051201齊齊哈爾:101050201大興安嶺:101050701長春:101060101延吉:101060301四平:101060401白山:101060901白城:101060601遼源:101060701松原:101060801吉林:101060201通化:101060501沈陽:101070101鞍山:101070301撫順:101070401本溪:101070501丹東:101070601葫蘆島:101071401營口:101070801阜新:101070901遼陽:101071001鐵嶺:101071101朝陽:101071201盤錦:101071301大連:101070201錦州:101070701判斷城市是否存在?
既然我們需要按城市查詢天氣預報,那么我們就需要判斷一下該城市是否存在,函數(shù)如下
"""判斷城市是否存在""" def Judge(city_name):city = re.compile(r'(?<={}:)\d*'.format(city_name))str1 = open('城市代碼.txt', 'r')new_str = str1.readlines()try:city_coding = city.search(str(new_str)).group(0)city_coding = city_namereturn city_nameexcept:return "你這兒是那個山卡卡"# print(city_coding)??這里用了正則,如果不熟悉正則的小伙伴,可以先在菜鳥教程在線正則編譯器進行正則的審核工作,這里也推薦一本關(guān)于正則的書《正則表達式必知必會》,這本書消化了的話,正則簡直就是信手拈來。
獲取url
接下來便是通過我們所需要查詢的城市,獲取相應的url,相應函數(shù)如下:
"""獲取url""" def getURL(city_name):base_url = 'http://www.weather.com.cn/weather/{}.shtml'city = re.compile(r'(?<={}:)\d*'.format(city_name))str1 = open('城市代碼.txt', 'r')# print(str.readlines())new_str = str1.readlines()# print(new_str)# print(city.search(str).group(0))city_coding = city.search(str(new_str)).group(0)# print(city_coding)#new_url = base_url.format(city_coding)# print(new_url)return new_urldef getURL2(city_name):base_url = 'http://www.weather.com.cn/weather15d/{}.shtml'city = re.compile(r'(?<={}:)\d*'.format(city_name))str1 = open('城市代碼.txt', 'r')# print(str.readlines())new_str = str1.readlines()# print(new_str)# print(city.search(str).group(0))city_coding = city.search(str(new_str)).group(0)# print(city_coding)#new_url = base_url.format(city_coding)# print(new_url)return new_url這里說一句,以前看著大家用format不以為意,結(jié)果自己寫了這個才知道format才是yyds。
這里面的open('城市代碼.txt', 'r'),中的'城市代碼.txt',需要大家自行創(chuàng)建一個txt文檔,然后把本文開頭發(fā)的城市代碼全部復制進去才可運行
請求獲取網(wǎng)頁內(nèi)容
我們獲取了url之后,就該通過相應的url請求網(wǎng)頁內(nèi)容了,
相關(guān)函數(shù)如下
"""請求獲得網(wǎng)頁內(nèi)容""" def getHTMLtext(url,city_name):"""請求獲得網(wǎng)頁內(nèi)容"""try:headers = {"User-Agent": UserAgent().random,}r = requests.get(url, timeout=30, headers=headers)r.raise_for_status()r.encoding = r.apparent_encodingprint("中國氣象網(wǎng){}24小時天氣訪問成功".format(city_name))return r.textexcept:print("中國氣象網(wǎng){}24小時天氣訪問失敗".format(city_name))return " "def getHTMLtext2(url,city_name):"""請求獲得網(wǎng)頁內(nèi)容"""try:headers = {"User-Agent": UserAgent().random,}r = requests.get(url, timeout=30, headers=headers)r.raise_for_status()r.encoding = r.apparent_encodingprint("中國氣象網(wǎng){}15天天氣訪問成功".format(city_name))return r.textexcept:print("中國氣象網(wǎng){}15天天氣訪問失敗".format(city_name))return " "這里用了一組try/except,本人不是太喜歡看到紅色報錯,所以如果訪問失敗,會直接返回print中的內(nèi)容?,前文也有一組,同樣的道理。
處理信息
處理有用的數(shù)據(jù),并暫時保存起來,
相關(guān)代碼如下
"""處理得到有用信息保存數(shù)據(jù)文件""" def get_content(html):final = [] # 初始化一個列表保存數(shù)據(jù)bs = BeautifulSoup(html, "html.parser") # 創(chuàng)建BeautifulSoup對象body = bs.bodydata = body.find('div', {'id': '7d'}) # 找到div標簽且id = 7d# 下面爬取當天的數(shù)據(jù)data2 = body.find_all('div', {'class': 'left-div'})text = data2[2].find('script').stringtext = text[text.index('=') + 1:-2] # 移除改var data=將其變?yōu)閖son數(shù)據(jù)jd = json.loads(text)dayone = jd['od']['od2'] # 找到當天的數(shù)據(jù)final_day = [] # 存放當天的數(shù)據(jù)count = 0for i in dayone:temp = []if count <= 23:temp.append(i['od21']) # 添加時間temp.append(i['od22']) # 添加當前時刻溫度temp.append(i['od24']) # 添加當前時刻風力方向temp.append(i['od25']) # 添加當前時刻風級temp.append(i['od26']) # 添加當前時刻降水量temp.append(i['od27']) # 添加當前時刻相對濕度temp.append(i['od28']) # 添加當前時刻控制質(zhì)量# print(temp)final_day.append(temp)count = count + 1return final_daydef get_content1_7(html):# 下面爬取7天的數(shù)據(jù)final = [] # 初始化一個列表保存數(shù)據(jù)bs = BeautifulSoup(html, "html.parser") # 創(chuàng)建BeautifulSoup對象body = bs.bodydata = body.find('div', {'id': '7d'}) # 找到div標簽且id = 7dul = data.find('ul') # 找到所有的ul標簽li = ul.find_all('li') # 找到左右的li標簽i = 0 # 控制爬取的天數(shù)for day in li: # 遍歷找到的每一個liif 7 > i > 0:temp = [] # 臨時存放每天的數(shù)據(jù)date = day.find('h1').string # 得到日期date = date[0:date.index('日')] # 取出日期號temp.append(date)inf = day.find_all('p') # 找出li下面的p標簽,提取第一個p標簽的值,即天氣temp.append(inf[0].string)tem_low = inf[1].find('i').string # 找到最低氣溫if inf[1].find('span') is None: # 天氣預報可能沒有最高氣溫tem_high = Noneelse:tem_high = inf[1].find('span').string # 找到最高氣溫temp.append(tem_low[:-1])if tem_high[-1] == '℃':temp.append(tem_high[:-1])else:temp.append(tem_high)wind = inf[2].find_all('span') # 找到風向for j in wind:temp.append(j['title'])wind_scale = inf[2].find('i').string # 找到風級index1 = wind_scale.index('級')temp.append(int(wind_scale[index1 - 1:index1]))final.append(temp)i = i + 1return finaldef get_content8_14(html):"""處理得到有用信息保存數(shù)據(jù)文件"""final = [] # 初始化一個列表保存數(shù)據(jù)bs = BeautifulSoup(html, "html.parser") # 創(chuàng)建BeautifulSoup對象body = bs.bodydata = body.find('div', {'id': '15d'}) # 找到div標簽且id = 15dul = data.find('ul') # 找到所有的ul標簽li = ul.find_all('li') # 找到左右的li標簽# final = []i = 0 # 控制爬取的天數(shù)for day in li: # 遍歷找到的每一個liif i < 8:temp = [] # 臨時存放每天的數(shù)據(jù)date = day.find('span', {'class': 'time'}).string # 得到日期date = date[date.index('(') + 1:-2] # 取出日期號temp.append(date)weather = day.find('span', {'class': 'wea'}).string # 找到天氣temp.append(weather)tem = day.find('span', {'class': 'tem'}).text # 找到溫度temp.append(tem[tem.index('/') + 1:-1]) # 找到最低氣溫temp.append(tem[:tem.index('/') - 1]) # 找到最高氣溫wind = day.find('span', {'class': 'wind'}).string # 找到風向if '轉(zhuǎn)' in wind: # 如果有風向變化temp.append(wind[:wind.index('轉(zhuǎn)')])temp.append(wind[wind.index('轉(zhuǎn)') + 1:])else: # 如果沒有風向變化,前后風向一致temp.append(wind)temp.append(wind)wind_scale = day.find('span', {'class': 'wind1'}).string # 找到風級index1 = wind_scale.index('級')temp.append(int(wind_scale[index1 - 1:index1]))final.append(temp)return final一開始我用的是XPath,但是這個中國氣象網(wǎng)中網(wǎng)頁源代碼,和網(wǎng)頁代碼不一樣,要用tbody,這個問題當時卡了我好幾天。?最后實在不想被惡心下去,又學了一下beautifusoup,用beautifulsoup解決了這里的問題。
保存csv
保存數(shù)據(jù)到csv文件,
、相關(guān)代碼如下
"""保存為csv文件""" def write_to_csv(file_name, data, day=14):"""保存為csv文件"""with open(file_name, 'w', errors='ignore', newline='') as f:if day == 14:header = ['日期', '天氣', '最低氣溫', '最高氣溫', '風向1', '風向2', '風級']else:header = ['小時', '溫度', '風力方向', '風級', '降水量', '相對濕度', '空氣質(zhì)量']f_csv = csv.writer(f)f_csv.writerow(header)f_csv.writerows(data)由于我們訪問了兩個網(wǎng)頁,訪問所暫存的數(shù)據(jù)也不一樣,所以我們需要判斷一下是24小時的數(shù)據(jù)還是14天的數(shù)據(jù)?
創(chuàng)建數(shù)據(jù)庫表單
"""創(chuàng)建表""" def Creat_Table(city_name):config = {"host": "localhost","port": "3306","user": "root","password": "628","database": "python"}con = mysql.connector.connect(**config)cursor = con.cursor()cursor.execute('DROP TABLE IF EXISTS {}weather'.format(city_name))sql_set = 'CREATE TABLE IF NOT EXISTS {}weather(Time INT,Temperature INT ,' \'wind_direction VARCHAR(255), wind INT, rainfall INT, Humidity INT)'.format(city_name)try:cursor.execute(sql_set)con.commit()print('創(chuàng)建{}24小時天氣情況數(shù)據(jù)表成功'.format(city_name))except:con.rollback()print("創(chuàng)建{}24小時天氣情況數(shù)據(jù)表失敗".format(city_name))con.close()def Creat_Table14(city_name):config = {"host": "localhost","port": "3306","user": "root","password": "628","database": "python"}con = mysql.connector.connect(**config)cursor = con.cursor()cursor.execute('DROP TABLE IF EXISTS {}weather14d'.format(city_name))sql_set = 'CREATE TABLE IF NOT EXISTS {}weather14d(Date INT,Weather VARCHAR(255) ,' \'Min_temperature INT, Max_temperature INT, wind_direction_1 VARCHAR(255), wind_direction_2 VARCHAR(255), wind_level INT)'.format(city_name)try:cursor.execute(sql_set)con.commit()print('創(chuàng)建{}15天天氣情況數(shù)據(jù)表成功'.format(city_name))except:con.rollback()print('創(chuàng)建{}15天天氣情況數(shù)據(jù)表失敗'.format(city_name))con.close()如果大家需要copy的話,記得改這兒的數(shù)據(jù)庫相應的值噢?
存儲數(shù)據(jù)到數(shù)據(jù)庫
??相關(guān)代碼如下
"""在表中插入數(shù)據(jù)""" def insert_data1(city_name):config = {"host": "localhost","port": "3306","user": "root","password": "628","database": "python"}con = mysql.connector.connect(**config)cursor = con.cursor()data1 = pd.read_csv('天氣預報-{}24小時天氣預報.csv'.format(city_name), encoding='gb2312')for i in range(data1.shape[0]):Time = list(data1['小時'])[i]Temperature = list(data1['溫度'])[i]wind_direction = list(data1['風力方向'])[i]wind = list(data1['風級'])[i]rainfall = list(data1['降水量'])[i]Humidity = list(data1['相對濕度'])[i]# Time = list(data1['空氣質(zhì)量'])[1]data = (Time, Temperature, wind_direction, wind, rainfall, Humidity)sql = "INSERT INTO {}weather(Time, Temperature, wind_direction, wind, rainfall, Humidity) values ".format(city_name) + str(data) + ";"try:cursor.execute(sql) #執(zhí)行sql語句con.commit() #連接提交except:con.rollback()print("插入{}24小時天氣情況數(shù)據(jù)失敗".format(city_name))print('插入{}24小時天氣情況數(shù)據(jù)成功'.format(city_name))cursor.close()con.close()# sql = "INSERT INTO weather(Time, Temperature, wind_direction, wind, rainfall, Humidity) values('1', '1', 's', '1', '1', '1');"# try:# cursor.execute(sql)# cursor.execute(sql)# con.commit()# print('插入數(shù)據(jù)成功')# except:# con.rollback()# print("插入數(shù)據(jù)失敗")# con.close()def insert_data14(city_name):config = {"host": "localhost","port": "3306","user": "root","password": "628","database": "python"}con = mysql.connector.connect(**config)cursor = con.cursor()data1 = pd.read_csv('天氣預報-{}15天天氣預報.csv'.format(city_name), encoding='gb2312')for i in range(data1.shape[0]):Date = list(data1['日期'])[i]Weather = list(data1['天氣'])[i]Min_temperature = list(data1['最低氣溫'])[i]Max_temperature = list(data1['最高氣溫'])[i]wind_direction_1 = list(data1['風向1'])[i]wind_direction_2 = list(data1['風向2'])[i]wind_level = list(data1['風級'])[i]# Time = list(data1['空氣質(zhì)量'])[1]data = (Date, Weather, Min_temperature, Max_temperature, wind_direction_1, wind_direction_2,wind_level)sql = "INSERT INTO {}weather14d(Date, Weather, Min_temperature, Max_temperature, wind_direction_1, wind_direction_2,wind_level) values ".format(city_name) + str(data) + ";"try:cursor.execute(sql) #執(zhí)行sql語句con.commit() #連接提交except:con.rollback()print("插入{}半個月天氣情況數(shù)據(jù)失敗")print('插入{}15天天氣情況數(shù)據(jù)成功'.format(city_name))cursor.close()con.close()?這個地方也給我卡了小半天,結(jié)果你們猜哪兒出問題了,最后檢查出來是保存14天數(shù)據(jù)的時候,寫sql語句時表單名字寫錯了。。。。。真的程序員的bug八成都是拼寫錯誤
數(shù)據(jù)爬取和數(shù)據(jù)存儲的事情我們都已經(jīng)完成了,接下來就需要數(shù)據(jù)可視化了,我用的是matplotlib,首先爬取天氣預報肯定要把每天的天氣溫度放首位,那么接下來我們繼續(xù)
繪制當天溫度曲線
def tem_curve(data,city_name ):"""溫度曲線繪制"""# plt.style.use('seaborn')hour = list(data['小時'])# print(hour)tem = list(data['溫度'])for i in range(0, 24):if math.isnan(tem[i]):tem[i] = tem[i - 1]tem_ave = sum(tem) / 24 # 求平均溫度tem_max = max(tem)tem_max_hour = hour[tem.index(tem_max)] # 求最高溫度tem_min = min(tem)tem_min_hour = hour[tem.index(tem_min)] # 求最低溫度x = []y = []for i in range(0, 24):x.append(i)y.append(tem[hour.index(i)])plt.style.use('seaborn')matplotlib.rcParams['font.sans-serif'] = ['SimHei']matplotlib.rcParams['axes.unicode_minus'] = Falseplt.figure(1)plt.plot(x, y, color='red', label='溫度',marker = '^') # 畫出溫度曲線plt.scatter(x, y, color='red') # 點出每個時刻的溫度點plt.plot([0, 24], [tem_ave, tem_ave], c='blue', linestyle='--', label='平均溫度') # 畫出平均溫度虛線plt.text(tem_max_hour + 0.15, tem_max + 0.15, str(tem_max), ha='center', va='bottom', fontsize=10.5) # 標出最高溫度plt.text(tem_min_hour + 0.15, tem_min + 0.15, str(tem_min), ha='center', va='bottom', fontsize=10.5) # 標出最低溫度plt.xticks(x)plt.legend()plt.title('一天溫度變化曲線圖')plt.xlabel('時間/h')plt.ylabel('攝氏度/℃')plt.savefig('image/{}24小時溫度曲線.png'.format(city_name), bbox_inches='tight')plt.show()?這段到后面的知識都是用了有關(guān)爬蟲可視化的知識,這里包括但不限于matplotlib,當時我學這個是在《Python從入門到實踐》這本書的可視化部分學的,這是圖靈出版的書,真的推薦大家去看看,特別適合新手入門
繪制15天溫度曲線
"""15天溫度曲線繪制""" def tem_curve14(data,city_name):date = list(data['日期'])tem_low = list(data['最低氣溫'])tem_high = list(data['最高氣溫'])for i in range(0, 14):if math.isnan(tem_low[i]):tem_low[i] = tem_low[i - 1]if math.isnan(tem_high[i]):tem_high[i] = tem_high[i - 1]tem_high_ave = sum(tem_high) / 14 # 求平均高溫tem_low_ave = sum(tem_low) / 14 # 求平均低溫tem_max = max(tem_high)tem_max_date = tem_high.index(tem_max) # 求最高溫度tem_min = min(tem_low)tem_min_date = tem_low.index(tem_min) # 求最低溫度x = range(1, 15)plt.figure(1)plt.plot(x, tem_high, color='red', label='高溫',marker = '^') # 畫出高溫度曲線plt.scatter(x, tem_high, color='red') # 點出每個時刻的溫度點plt.plot(x, tem_low, color='blue', label='低溫',marker = '^') # 畫出低溫度曲線plt.scatter(x, tem_low, color='blue') # 點出每個時刻的溫度點plt.plot([1, 15], [tem_high_ave, tem_high_ave], c='black', linestyle='--') # 畫出平均溫度虛線plt.plot([1, 15], [tem_low_ave, tem_low_ave], c='black', linestyle='--') # 畫出平均溫度虛線plt.legend()plt.text(tem_max_date + 0.15, tem_max + 0.15, str(tem_max), ha='center', va='bottom', fontsize=10.5) # 標出最高溫度plt.text(tem_min_date + 0.15, tem_min + 0.15, str(tem_min), ha='center', va='bottom', fontsize=10.5) # 標出最低溫度plt.xticks(x)plt.title('未來14天高溫低溫變化曲線圖')plt.xlabel('未來天數(shù)/天')plt.ylabel('攝氏度/℃')plt.savefig('image/{}15天溫度曲線.png'.format(city_name), bbox_inches='tight')plt.show()相對濕度曲線繪制
"""相對濕度曲線繪制""" def hum_curve(data,city_name):"""相對濕度曲線繪制"""hour = list(data['小時'])hum = list(data['相對濕度'])for i in range(0, 24):if math.isnan(hum[i]) == True:hum[i] = hum[i - 1]hum_ave = sum(hum) / 24 # 求平均相對濕度hum_max = max(hum)hum_max_hour = hour[hum.index(hum_max)] # 求最高相對濕度hum_min = min(hum)hum_min_hour = hour[hum.index(hum_min)] # 求最低相對濕度x = []y = []for i in range(0, 24):x.append(i)y.append(hum[hour.index(i)])plt.figure(2)plt.plot(x, y, color='blue', label='相對濕度',marker = '^') # 畫出相對濕度曲線plt.scatter(x, y, color='blue') # 點出每個時刻的相對濕度plt.plot([0, 24], [hum_ave, hum_ave], c='red', linestyle='--', label='平均相對濕度',marker = '*') # 畫出平均相對濕度虛線plt.text(hum_max_hour + 0.15, hum_max + 0.15, str(hum_max), ha='center', va='bottom', fontsize=10.5) # 標出最高相對濕度plt.text(hum_min_hour + 0.15, hum_min + 0.15, str(hum_min), ha='center', va='bottom', fontsize=10.5) # 標出最低相對濕度plt.xticks(x)plt.legend()plt.title('一天相對濕度變化曲線圖')plt.xlabel('時間/h')plt.ylabel('百分比/%')plt.savefig('image/{}相對濕度曲線.png'.format(city_name), bbox_inches='tight')plt.show()空氣質(zhì)量曲線繪制
"""空氣質(zhì)量曲線繪制""" def air_curve(data,city_name):"""空氣質(zhì)量曲線繪制"""hour = list(data['小時'])air = list(data['空氣質(zhì)量'])# print(type(air[0]))for i in range(0, 24):if math.isnan(air[i]) == True:air[i] = air[i - 1]air_ave = sum(air) / 24 # 求平均空氣質(zhì)量air_max = max(air)air_max_hour = hour[air.index(air_max)] # 求最高空氣質(zhì)量air_min = min(air)air_min_hour = hour[air.index(air_min)] # 求最低空氣質(zhì)量x = []y = []for i in range(0, 24):x.append(i)y.append(air[hour.index(i)])plt.figure(3)for i in range(0, 24):if y[i] <= 50:plt.bar(x[i], y[i], color='lightgreen', width=0.7) # 1等級elif y[i] <= 100:plt.bar(x[i], y[i], color='wheat', width=0.7) # 2等級elif y[i] <= 150:plt.bar(x[i], y[i], color='orange', width=0.7) # 3等級elif y[i] <= 200:plt.bar(x[i], y[i], color='orangered', width=0.7) # 4等級elif y[i] <= 300:plt.bar(x[i], y[i], color='darkviolet', width=0.7) # 5等級elif y[i] > 300:plt.bar(x[i], y[i], color='maroon', width=0.7) # 6等級plt.plot([0, 24], [air_ave, air_ave], c='black', linestyle='--') # 畫出平均空氣質(zhì)量虛線plt.text(air_max_hour + 0.15, air_max + 0.15, str(air_max), ha='center', va='bottom', fontsize=10.5) # 標出最高空氣質(zhì)量plt.text(air_min_hour + 0.15, air_min + 0.15, str(air_min), ha='center', va='bottom', fontsize=10.5) # 標出最低空氣質(zhì)量plt.xticks(x)plt.title('一天空氣質(zhì)量變化曲線圖')plt.xlabel('時間/h')plt.ylabel('空氣質(zhì)量指數(shù)AQI')plt.savefig('image/{}空氣質(zhì)量曲線.png'.format(city_name), bbox_inches='tight')plt.show()風向雷達圖繪制
"""改變風向""" def change_wind(wind):for i in range(0, 14):if wind[i] == "北風":wind[i] = 90elif wind[i] == "南風":wind[i] = 270elif wind[i] == "西風":wind[i] = 180elif wind[i] == "東風":wind[i] = 360elif wind[i] == "東北風":wind[i] = 45elif wind[i] == "西北風":wind[i] = 135elif wind[i] == "西南風":wind[i] = 225elif wind[i] == "東南風":wind[i] = 315return wind"""風向雷達圖""" def wind_radar(data,city_name):wind1 = list(data['風向1'])wind2 = list(data['風向2'])wind_speed = list(data['風級'])wind1 = change_wind(wind1)wind2 = change_wind(wind2)degs = np.arange(45, 361, 45)temp = []for deg in degs:speed = []# 獲取 wind_deg 在指定范圍的風速平均值數(shù)據(jù)for i in range(0, 14):if wind1[i] == deg:speed.append(wind_speed[i])if wind2[i] == deg:speed.append(wind_speed[i])if len(speed) == 0:temp.append(0)else:temp.append(sum(speed) / len(speed))# print(temp)N = 8theta = np.arange(0. + np.pi / 8, 2 * np.pi + np.pi / 8, 2 * np.pi / 8)# 數(shù)據(jù)極徑radii = np.array(temp)# 繪制極區(qū)圖坐標系plt.axes(polar=True)# 定義每個扇區(qū)的RGB值(R,G,B),x越大,對應的顏色越接近藍色colors = [(1 - x / max(temp), 1 - x / max(temp), 0.6) for x in radii]plt.bar(theta, radii, width=(2 * np.pi / N), bottom=0.0, color=colors)plt.title('未來14天風級圖', x=0.2, fontsize=20)plt.savefig('image/{}風向曲線.png'.format(city_name), bbox_inches='tight')plt.show()繪制天氣餅圖
"""繪制天氣餅圖""" def weather_pie(data,city_name):weather = list(data['天氣'])dic_wea = {}for i in range(0, 14):if weather[i] in dic_wea.keys():dic_wea[weather[i]] += 1else:dic_wea[weather[i]] = 1# print(dic_wea)explode = [0.01] * len(dic_wea.keys())color = ['lightskyblue', 'silver', 'yellow', 'salmon', 'grey', 'lime', 'gold', 'red', 'green', 'pink']plt.pie(dic_wea.values(), explode=explode, labels=dic_wea.keys(), autopct='%1.1f%%', colors=color)plt.title('未來14天氣候分布餅圖')plt.savefig('image/{}天氣餅圖.png'.format(city_name), bbox_inches='tight')plt.show()main主函數(shù)
def main():"""主函數(shù)"""city_name = input("請輸入要查詢的城市:")judge = Judge(city_name)while judge == "你這兒是那個山卡卡":print("你勒兒是那個山卡卡,我查不到,你換個塔塔誒")city_name = input("請輸入要查詢的城市:")judge = Judge(city_name)print(judge)if judge == city_name:url_1 = getURL(city_name) # 7天天氣中國天氣網(wǎng)# print(url_1)url_2 = getURL2(city_name)html1 = getHTMLtext(url_1,city_name)data1 = get_content(html1) # 獲得1-7天和當天的數(shù)據(jù)data1_7 = get_content1_7(html1)html2 = getHTMLtext2(url_2,city_name)data8_14 = get_content8_14(html2)data14 = data1_7 + data8_14write_to_csv('天氣預報-{}24小時天氣預報.csv'.format(city_name), data1, 1)write_to_csv('天氣預報-{}15天天氣預報.csv'.format(city_name), data14, 14)Creat_Table(city_name)Creat_Table14(city_name)insert_data1(city_name)insert_data14(city_name)plt.style.use('seaborn')matplotlib.rcParams['font.sans-serif'] = ['SimHei'] # 解決中文顯示問題matplotlib.rcParams['axes.unicode_minus'] = False # 解決負號顯示問題data1 = pd.read_csv('天氣預報-{}24小時天氣預報.csv'.format(city_name), encoding='gb2312')data14 = pd.read_csv('天氣預報-{}15天天氣預報.csv'.format(city_name), encoding='gb2312')# tem_curve(data1,city_name) #24小時溫度曲線繪制# hum_curve(data1,city_name) #相對濕度曲線繪制# air_curve(data1,city_name) #空氣質(zhì)量曲線繪制# corr_tem_hum(data1,city_name) #溫濕度相關(guān)性分析# tem_curve14(data14,city_name) #15天溫度曲線繪制# wind_radar(data14,city_name) #風向雷達圖# weather_pie(data14,city_name) #繪制天氣餅圖while True:num = int(input("請輸入要查詢的圖表(輸入1查詢24小時溫度曲線繪制、輸入2查詢相對濕度曲線繪制、""輸入3查詢空氣質(zhì)量曲線繪制、輸入4查詢15天溫度曲線、輸入5風向雷達圖、""輸入6天氣餅圖):"))if num == 1:tem_curve(data1,city_name) #24小時溫度曲線繪制elif num == 2:hum_curve(data1,city_name) #相對濕度曲線繪制elif num == 3:air_curve(data1,city_name) #空氣質(zhì)量曲線繪制elif num == 4:tem_curve14(data14, city_name) # 15天溫度曲線繪制elif num == 5:wind_radar(data14, city_name) # 風向雷達圖elif num == 6:weather_pie(data14, city_name) # 繪制天氣餅圖else:print("查詢結(jié)束...")return False第一個whlie這兒做了一個判斷,如果搜索的城市不存在,會繼續(xù)讓你進行搜索,如果存在,就會往下繼續(xù)運行。
第二個while是做了個簡單的查詢,這個思路來自老師開課的第一課給我們的點名系統(tǒng),對應的數(shù)字有對應的繪圖?,輸入以外的數(shù)字將彈出循環(huán),程序結(jié)束
全部代碼展示
import requests from fake_useragent import UserAgent import json from bs4 import BeautifulSoup import csv import pandas as pd import matplotlib.pyplot as plt import math import mysql.connector import re import numpy as np import matplotlib"""判斷城市是否存在""" def Judge(city_name):city = re.compile(r'(?<={}:)\d*'.format(city_name))str1 = open('城市代碼.txt', 'r')new_str = str1.readlines()try:city_coding = city.search(str(new_str)).group(0)city_coding = city_namereturn city_nameexcept:return "你這兒是那個山卡卡"# print(city_coding)"""獲取url""" def getURL(city_name):base_url = 'http://www.weather.com.cn/weather/{}.shtml'city = re.compile(r'(?<={}:)\d*'.format(city_name))str1 = open('城市代碼.txt', 'r')# print(str.readlines())new_str = str1.readlines()# print(new_str)# print(city.search(str).group(0))city_coding = city.search(str(new_str)).group(0)# print(city_coding)#new_url = base_url.format(city_coding)# print(new_url)return new_urldef getURL2(city_name):base_url = 'http://www.weather.com.cn/weather15d/{}.shtml'city = re.compile(r'(?<={}:)\d*'.format(city_name))str1 = open('城市代碼.txt', 'r')# print(str.readlines())new_str = str1.readlines()# print(new_str)# print(city.search(str).group(0))city_coding = city.search(str(new_str)).group(0)# print(city_coding)#new_url = base_url.format(city_coding)# print(new_url)return new_url"""請求獲得網(wǎng)頁內(nèi)容""" def getHTMLtext(url,city_name):"""請求獲得網(wǎng)頁內(nèi)容"""try:headers = {"User-Agent": UserAgent().random,}r = requests.get(url, timeout=30, headers=headers)r.raise_for_status()r.encoding = r.apparent_encodingprint("中國氣象網(wǎng){}24小時天氣訪問成功".format(city_name))return r.textexcept:print("中國氣象網(wǎng){}24小時天氣訪問失敗".format(city_name))return " "def getHTMLtext2(url,city_name):"""請求獲得網(wǎng)頁內(nèi)容"""try:headers = {"User-Agent": UserAgent().random,}r = requests.get(url, timeout=30, headers=headers)r.raise_for_status()r.encoding = r.apparent_encodingprint("中國氣象網(wǎng){}15天天氣訪問成功".format(city_name))return r.textexcept:print("中國氣象網(wǎng){}15天天氣訪問失敗".format(city_name))return " """"處理得到有用信息保存數(shù)據(jù)文件""" def get_content(html):final = [] # 初始化一個列表保存數(shù)據(jù)bs = BeautifulSoup(html, "html.parser") # 創(chuàng)建BeautifulSoup對象body = bs.bodydata = body.find('div', {'id': '7d'}) # 找到div標簽且id = 7d# 下面爬取當天的數(shù)據(jù)data2 = body.find_all('div', {'class': 'left-div'})text = data2[2].find('script').stringtext = text[text.index('=') + 1:-2] # 移除改var data=將其變?yōu)閖son數(shù)據(jù)jd = json.loads(text)dayone = jd['od']['od2'] # 找到當天的數(shù)據(jù)final_day = [] # 存放當天的數(shù)據(jù)count = 0for i in dayone:temp = []if count <= 23:temp.append(i['od21']) # 添加時間temp.append(i['od22']) # 添加當前時刻溫度temp.append(i['od24']) # 添加當前時刻風力方向temp.append(i['od25']) # 添加當前時刻風級temp.append(i['od26']) # 添加當前時刻降水量temp.append(i['od27']) # 添加當前時刻相對濕度temp.append(i['od28']) # 添加當前時刻控制質(zhì)量# print(temp)final_day.append(temp)count = count + 1return final_daydef get_content1_7(html):# 下面爬取7天的數(shù)據(jù)final = [] # 初始化一個列表保存數(shù)據(jù)bs = BeautifulSoup(html, "html.parser") # 創(chuàng)建BeautifulSoup對象body = bs.bodydata = body.find('div', {'id': '7d'}) # 找到div標簽且id = 7dul = data.find('ul') # 找到所有的ul標簽li = ul.find_all('li') # 找到左右的li標簽i = 0 # 控制爬取的天數(shù)for day in li: # 遍歷找到的每一個liif 7 > i > 0:temp = [] # 臨時存放每天的數(shù)據(jù)date = day.find('h1').string # 得到日期date = date[0:date.index('日')] # 取出日期號temp.append(date)inf = day.find_all('p') # 找出li下面的p標簽,提取第一個p標簽的值,即天氣temp.append(inf[0].string)tem_low = inf[1].find('i').string # 找到最低氣溫if inf[1].find('span') is None: # 天氣預報可能沒有最高氣溫tem_high = Noneelse:tem_high = inf[1].find('span').string # 找到最高氣溫temp.append(tem_low[:-1])if tem_high[-1] == '℃':temp.append(tem_high[:-1])else:temp.append(tem_high)wind = inf[2].find_all('span') # 找到風向for j in wind:temp.append(j['title'])wind_scale = inf[2].find('i').string # 找到風級index1 = wind_scale.index('級')temp.append(int(wind_scale[index1 - 1:index1]))final.append(temp)i = i + 1return finaldef get_content8_14(html):"""處理得到有用信息保存數(shù)據(jù)文件"""final = [] # 初始化一個列表保存數(shù)據(jù)bs = BeautifulSoup(html, "html.parser") # 創(chuàng)建BeautifulSoup對象body = bs.bodydata = body.find('div', {'id': '15d'}) # 找到div標簽且id = 15dul = data.find('ul') # 找到所有的ul標簽li = ul.find_all('li') # 找到左右的li標簽# final = []i = 0 # 控制爬取的天數(shù)for day in li: # 遍歷找到的每一個liif i < 8:temp = [] # 臨時存放每天的數(shù)據(jù)date = day.find('span', {'class': 'time'}).string # 得到日期date = date[date.index('(') + 1:-2] # 取出日期號temp.append(date)weather = day.find('span', {'class': 'wea'}).string # 找到天氣temp.append(weather)tem = day.find('span', {'class': 'tem'}).text # 找到溫度temp.append(tem[tem.index('/') + 1:-1]) # 找到最低氣溫temp.append(tem[:tem.index('/') - 1]) # 找到最高氣溫wind = day.find('span', {'class': 'wind'}).string # 找到風向if '轉(zhuǎn)' in wind: # 如果有風向變化temp.append(wind[:wind.index('轉(zhuǎn)')])temp.append(wind[wind.index('轉(zhuǎn)') + 1:])else: # 如果沒有風向變化,前后風向一致temp.append(wind)temp.append(wind)wind_scale = day.find('span', {'class': 'wind1'}).string # 找到風級index1 = wind_scale.index('級')temp.append(int(wind_scale[index1 - 1:index1]))final.append(temp)return final"""保存為csv文件""" def write_to_csv(file_name, data, day=14):"""保存為csv文件"""with open(file_name, 'w', errors='ignore', newline='') as f:if day == 14:header = ['日期', '天氣', '最低氣溫', '最高氣溫', '風向1', '風向2', '風級']else:header = ['小時', '溫度', '風力方向', '風級', '降水量', '相對濕度', '空氣質(zhì)量']f_csv = csv.writer(f)f_csv.writerow(header)f_csv.writerows(data)"""創(chuàng)建表""" def Creat_Table(city_name):config = {"host": "localhost","port": "3306","user": "root","password": "628","database": "python"}con = mysql.connector.connect(**config)cursor = con.cursor()cursor.execute('DROP TABLE IF EXISTS {}weather'.format(city_name))sql_set = 'CREATE TABLE IF NOT EXISTS {}weather(Time INT,Temperature INT ,' \'wind_direction VARCHAR(255), wind INT, rainfall INT, Humidity INT)'.format(city_name)try:cursor.execute(sql_set)con.commit()print('創(chuàng)建{}24小時天氣情況數(shù)據(jù)表成功'.format(city_name))except:con.rollback()print("創(chuàng)建{}24小時天氣情況數(shù)據(jù)表失敗".format(city_name))con.close()def Creat_Table14(city_name):config = {"host": "localhost","port": "3306","user": "root","password": "628","database": "python"}con = mysql.connector.connect(**config)cursor = con.cursor()cursor.execute('DROP TABLE IF EXISTS {}weather14d'.format(city_name))sql_set = 'CREATE TABLE IF NOT EXISTS {}weather14d(Date INT,Weather VARCHAR(255) ,' \'Min_temperature INT, Max_temperature INT, wind_direction_1 VARCHAR(255), wind_direction_2 VARCHAR(255), wind_level INT)'.format(city_name)try:cursor.execute(sql_set)con.commit()print('創(chuàng)建{}15天天氣情況數(shù)據(jù)表成功'.format(city_name))except:con.rollback()print('創(chuàng)建{}15天天氣情況數(shù)據(jù)表失敗'.format(city_name))con.close()"""在表中插入數(shù)據(jù)""" def insert_data1(city_name):config = {"host": "localhost","port": "3306","user": "root","password": "628","database": "python"}con = mysql.connector.connect(**config)cursor = con.cursor()data1 = pd.read_csv('天氣預報-{}24小時天氣預報.csv'.format(city_name), encoding='gb2312')for i in range(data1.shape[0]):Time = list(data1['小時'])[i]Temperature = list(data1['溫度'])[i]wind_direction = list(data1['風力方向'])[i]wind = list(data1['風級'])[i]rainfall = list(data1['降水量'])[i]Humidity = list(data1['相對濕度'])[i]# Time = list(data1['空氣質(zhì)量'])[1]data = (Time, Temperature, wind_direction, wind, rainfall, Humidity)sql = "INSERT INTO {}weather(Time, Temperature, wind_direction, wind, rainfall, Humidity) values ".format(city_name) + str(data) + ";"try:cursor.execute(sql) #執(zhí)行sql語句con.commit() #連接提交except:con.rollback()print("插入{}24小時天氣情況數(shù)據(jù)失敗".format(city_name))print('插入{}24小時天氣情況數(shù)據(jù)成功'.format(city_name))cursor.close()con.close()# sql = "INSERT INTO weather(Time, Temperature, wind_direction, wind, rainfall, Humidity) values('1', '1', 's', '1', '1', '1');"# try:# cursor.execute(sql)# cursor.execute(sql)# con.commit()# print('插入數(shù)據(jù)成功')# except:# con.rollback()# print("插入數(shù)據(jù)失敗")# con.close()def insert_data14(city_name):config = {"host": "localhost","port": "3306","user": "root","password": "628","database": "python"}con = mysql.connector.connect(**config)cursor = con.cursor()data1 = pd.read_csv('天氣預報-{}15天天氣預報.csv'.format(city_name), encoding='gb2312')for i in range(data1.shape[0]):Date = list(data1['日期'])[i]Weather = list(data1['天氣'])[i]Min_temperature = list(data1['最低氣溫'])[i]Max_temperature = list(data1['最高氣溫'])[i]wind_direction_1 = list(data1['風向1'])[i]wind_direction_2 = list(data1['風向2'])[i]wind_level = list(data1['風級'])[i]# Time = list(data1['空氣質(zhì)量'])[1]data = (Date, Weather, Min_temperature, Max_temperature, wind_direction_1, wind_direction_2,wind_level)sql = "INSERT INTO {}weather14d(Date, Weather, Min_temperature, Max_temperature, wind_direction_1, wind_direction_2,wind_level) values ".format(city_name) + str(data) + ";"try:cursor.execute(sql) #執(zhí)行sql語句con.commit() #連接提交except:con.rollback()print("插入{}半個月天氣情況數(shù)據(jù)失敗")print('插入{}15天天氣情況數(shù)據(jù)成功'.format(city_name))cursor.close()con.close()"""溫度曲線繪制""" def tem_curve(data,city_name ):"""溫度曲線繪制"""# plt.style.use('seaborn')hour = list(data['小時'])# print(hour)tem = list(data['溫度'])for i in range(0, 24):if math.isnan(tem[i]):tem[i] = tem[i - 1]tem_ave = sum(tem) / 24 # 求平均溫度tem_max = max(tem)tem_max_hour = hour[tem.index(tem_max)] # 求最高溫度tem_min = min(tem)tem_min_hour = hour[tem.index(tem_min)] # 求最低溫度x = []y = []for i in range(0, 24):x.append(i)y.append(tem[hour.index(i)])plt.style.use('seaborn')matplotlib.rcParams['font.sans-serif'] = ['SimHei']matplotlib.rcParams['axes.unicode_minus'] = Falseplt.figure(1)plt.plot(x, y, color='red', label='溫度',marker = '^') # 畫出溫度曲線plt.scatter(x, y, color='red') # 點出每個時刻的溫度點plt.plot([0, 24], [tem_ave, tem_ave], c='blue', linestyle='--', label='平均溫度') # 畫出平均溫度虛線plt.text(tem_max_hour + 0.15, tem_max + 0.15, str(tem_max), ha='center', va='bottom', fontsize=10.5) # 標出最高溫度plt.text(tem_min_hour + 0.15, tem_min + 0.15, str(tem_min), ha='center', va='bottom', fontsize=10.5) # 標出最低溫度plt.xticks(x)plt.legend()plt.title('一天溫度變化曲線圖')plt.xlabel('時間/h')plt.ylabel('攝氏度/℃')plt.savefig('image/{}24小時溫度曲線.png'.format(city_name), bbox_inches='tight')plt.show()"""相對濕度曲線繪制""" def hum_curve(data,city_name):"""相對濕度曲線繪制"""hour = list(data['小時'])hum = list(data['相對濕度'])for i in range(0, 24):if math.isnan(hum[i]) == True:hum[i] = hum[i - 1]hum_ave = sum(hum) / 24 # 求平均相對濕度hum_max = max(hum)hum_max_hour = hour[hum.index(hum_max)] # 求最高相對濕度hum_min = min(hum)hum_min_hour = hour[hum.index(hum_min)] # 求最低相對濕度x = []y = []for i in range(0, 24):x.append(i)y.append(hum[hour.index(i)])plt.figure(2)plt.plot(x, y, color='blue', label='相對濕度',marker = '^') # 畫出相對濕度曲線plt.scatter(x, y, color='blue') # 點出每個時刻的相對濕度plt.plot([0, 24], [hum_ave, hum_ave], c='red', linestyle='--', label='平均相對濕度',marker = '*') # 畫出平均相對濕度虛線plt.text(hum_max_hour + 0.15, hum_max + 0.15, str(hum_max), ha='center', va='bottom', fontsize=10.5) # 標出最高相對濕度plt.text(hum_min_hour + 0.15, hum_min + 0.15, str(hum_min), ha='center', va='bottom', fontsize=10.5) # 標出最低相對濕度plt.xticks(x)plt.legend()plt.title('一天相對濕度變化曲線圖')plt.xlabel('時間/h')plt.ylabel('百分比/%')plt.savefig('image/{}相對濕度曲線.png'.format(city_name), bbox_inches='tight')plt.show()"""空氣質(zhì)量曲線繪制""" def air_curve(data,city_name):"""空氣質(zhì)量曲線繪制"""hour = list(data['小時'])air = list(data['空氣質(zhì)量'])# print(type(air[0]))for i in range(0, 24):if math.isnan(air[i]) == True:air[i] = air[i - 1]air_ave = sum(air) / 24 # 求平均空氣質(zhì)量air_max = max(air)air_max_hour = hour[air.index(air_max)] # 求最高空氣質(zhì)量air_min = min(air)air_min_hour = hour[air.index(air_min)] # 求最低空氣質(zhì)量x = []y = []for i in range(0, 24):x.append(i)y.append(air[hour.index(i)])plt.figure(3)for i in range(0, 24):if y[i] <= 50:plt.bar(x[i], y[i], color='lightgreen', width=0.7) # 1等級elif y[i] <= 100:plt.bar(x[i], y[i], color='wheat', width=0.7) # 2等級elif y[i] <= 150:plt.bar(x[i], y[i], color='orange', width=0.7) # 3等級elif y[i] <= 200:plt.bar(x[i], y[i], color='orangered', width=0.7) # 4等級elif y[i] <= 300:plt.bar(x[i], y[i], color='darkviolet', width=0.7) # 5等級elif y[i] > 300:plt.bar(x[i], y[i], color='maroon', width=0.7) # 6等級plt.plot([0, 24], [air_ave, air_ave], c='black', linestyle='--') # 畫出平均空氣質(zhì)量虛線plt.text(air_max_hour + 0.15, air_max + 0.15, str(air_max), ha='center', va='bottom', fontsize=10.5) # 標出最高空氣質(zhì)量plt.text(air_min_hour + 0.15, air_min + 0.15, str(air_min), ha='center', va='bottom', fontsize=10.5) # 標出最低空氣質(zhì)量plt.xticks(x)plt.title('一天空氣質(zhì)量變化曲線圖')plt.xlabel('時間/h')plt.ylabel('空氣質(zhì)量指數(shù)AQI')plt.savefig('image/{}空氣質(zhì)量曲線.png'.format(city_name), bbox_inches='tight')plt.show()"""計算相關(guān)系數(shù)""" def calc_corr(a, b):"""計算相關(guān)系數(shù)"""a_avg = sum(a) / len(a)b_avg = sum(b) / len(b)cov_ab = sum([(x - a_avg) * (y - b_avg) for x, y in zip(a, b)])sq = math.sqrt(sum([(x - a_avg) ** 2 for x in a]) * sum([(x - b_avg) ** 2 for x in b]))corr_factor = cov_ab / sqreturn corr_factor"""溫濕度相關(guān)性分析""" def corr_tem_hum(data,city_name):"""溫濕度相關(guān)性分析"""tem = data['溫度']hum = data['相對濕度']plt.scatter(tem, hum, color='blue')plt.title("溫濕度相關(guān)性分析圖")plt.xlabel("溫度/℃")plt.ylabel("相對濕度/%")# plt.text(13, 40, "相關(guān)系數(shù)為:" + str(calc_corr(tem, hum)), fontdict={'size': '10', 'color': 'red'})plt.savefig('image/{}溫濕度相關(guān)性.png'.format(city_name), bbox_inches='tight')plt.show()# print("相關(guān)系數(shù)為:" + str(calc_corr(tem, hum)))"""15天溫度曲線繪制""" def tem_curve14(data,city_name):date = list(data['日期'])tem_low = list(data['最低氣溫'])tem_high = list(data['最高氣溫'])for i in range(0, 14):if math.isnan(tem_low[i]):tem_low[i] = tem_low[i - 1]if math.isnan(tem_high[i]):tem_high[i] = tem_high[i - 1]tem_high_ave = sum(tem_high) / 14 # 求平均高溫tem_low_ave = sum(tem_low) / 14 # 求平均低溫tem_max = max(tem_high)tem_max_date = tem_high.index(tem_max) # 求最高溫度tem_min = min(tem_low)tem_min_date = tem_low.index(tem_min) # 求最低溫度x = range(1, 15)plt.figure(1)plt.plot(x, tem_high, color='red', label='高溫',marker = '^') # 畫出高溫度曲線plt.scatter(x, tem_high, color='red') # 點出每個時刻的溫度點plt.plot(x, tem_low, color='blue', label='低溫',marker = '^') # 畫出低溫度曲線plt.scatter(x, tem_low, color='blue') # 點出每個時刻的溫度點plt.plot([1, 15], [tem_high_ave, tem_high_ave], c='black', linestyle='--') # 畫出平均溫度虛線plt.plot([1, 15], [tem_low_ave, tem_low_ave], c='black', linestyle='--') # 畫出平均溫度虛線plt.legend()plt.text(tem_max_date + 0.15, tem_max + 0.15, str(tem_max), ha='center', va='bottom', fontsize=10.5) # 標出最高溫度plt.text(tem_min_date + 0.15, tem_min + 0.15, str(tem_min), ha='center', va='bottom', fontsize=10.5) # 標出最低溫度plt.xticks(x)plt.title('未來14天高溫低溫變化曲線圖')plt.xlabel('未來天數(shù)/天')plt.ylabel('攝氏度/℃')plt.savefig('image/{}15天溫度曲線.png'.format(city_name), bbox_inches='tight')plt.show()"""改變風向""" def change_wind(wind):for i in range(0, 14):if wind[i] == "北風":wind[i] = 90elif wind[i] == "南風":wind[i] = 270elif wind[i] == "西風":wind[i] = 180elif wind[i] == "東風":wind[i] = 360elif wind[i] == "東北風":wind[i] = 45elif wind[i] == "西北風":wind[i] = 135elif wind[i] == "西南風":wind[i] = 225elif wind[i] == "東南風":wind[i] = 315return wind"""風向雷達圖""" def wind_radar(data,city_name):wind1 = list(data['風向1'])wind2 = list(data['風向2'])wind_speed = list(data['風級'])wind1 = change_wind(wind1)wind2 = change_wind(wind2)degs = np.arange(45, 361, 45)temp = []for deg in degs:speed = []# 獲取 wind_deg 在指定范圍的風速平均值數(shù)據(jù)for i in range(0, 14):if wind1[i] == deg:speed.append(wind_speed[i])if wind2[i] == deg:speed.append(wind_speed[i])if len(speed) == 0:temp.append(0)else:temp.append(sum(speed) / len(speed))# print(temp)N = 8theta = np.arange(0. + np.pi / 8, 2 * np.pi + np.pi / 8, 2 * np.pi / 8)# 數(shù)據(jù)極徑radii = np.array(temp)# 繪制極區(qū)圖坐標系plt.axes(polar=True)# 定義每個扇區(qū)的RGB值(R,G,B),x越大,對應的顏色越接近藍色colors = [(1 - x / max(temp), 1 - x / max(temp), 0.6) for x in radii]plt.bar(theta, radii, width=(2 * np.pi / N), bottom=0.0, color=colors)plt.title('未來14天風級圖', x=0.2, fontsize=20)plt.savefig('image/{}風向曲線.png'.format(city_name), bbox_inches='tight')plt.show()"""繪制天氣餅圖""" def weather_pie(data,city_name):weather = list(data['天氣'])dic_wea = {}for i in range(0, 14):if weather[i] in dic_wea.keys():dic_wea[weather[i]] += 1else:dic_wea[weather[i]] = 1# print(dic_wea)explode = [0.01] * len(dic_wea.keys())color = ['lightskyblue', 'silver', 'yellow', 'salmon', 'grey', 'lime', 'gold', 'red', 'green', 'pink']plt.pie(dic_wea.values(), explode=explode, labels=dic_wea.keys(), autopct='%1.1f%%', colors=color)plt.title('未來14天氣候分布餅圖')plt.savefig('image/{}天氣餅圖.png'.format(city_name), bbox_inches='tight')plt.show()def main():"""主函數(shù)"""city_name = input("請輸入要查詢的城市:")judge = Judge(city_name)while judge == "你這兒是那個山卡卡":print("你勒兒是那個山卡卡,我查不到,你換個塔塔誒")city_name = input("請輸入要查詢的城市:")judge = Judge(city_name)print(judge)if judge == city_name:url_1 = getURL(city_name) # 7天天氣中國天氣網(wǎng)# print(url_1)url_2 = getURL2(city_name)html1 = getHTMLtext(url_1,city_name)data1 = get_content(html1) # 獲得1-7天和當天的數(shù)據(jù)data1_7 = get_content1_7(html1)html2 = getHTMLtext2(url_2,city_name)data8_14 = get_content8_14(html2)data14 = data1_7 + data8_14write_to_csv('天氣預報-{}24小時天氣預報.csv'.format(city_name), data1, 1)write_to_csv('天氣預報-{}15天天氣預報.csv'.format(city_name), data14, 14)Creat_Table(city_name)Creat_Table14(city_name)insert_data1(city_name)insert_data14(city_name)plt.style.use('seaborn')matplotlib.rcParams['font.sans-serif'] = ['SimHei'] # 解決中文顯示問題matplotlib.rcParams['axes.unicode_minus'] = False # 解決負號顯示問題data1 = pd.read_csv('天氣預報-{}24小時天氣預報.csv'.format(city_name), encoding='gb2312')data14 = pd.read_csv('天氣預報-{}15天天氣預報.csv'.format(city_name), encoding='gb2312')# tem_curve(data1,city_name) #24小時溫度曲線繪制# hum_curve(data1,city_name) #相對濕度曲線繪制# air_curve(data1,city_name) #空氣質(zhì)量曲線繪制# corr_tem_hum(data1,city_name) #溫濕度相關(guān)性分析# tem_curve14(data14,city_name) #15天溫度曲線繪制# wind_radar(data14,city_name) #風向雷達圖# weather_pie(data14,city_name) #繪制天氣餅圖while True:num = int(input("請輸入要查詢的圖表(輸入1查詢24小時溫度曲線繪制、輸入2查詢相對濕度曲線繪制、""輸入3查詢空氣質(zhì)量曲線繪制、輸入4查詢15天溫度曲線、輸入5風向雷達圖、""輸入6天氣餅圖圖):"))if num == 1:tem_curve(data1,city_name) #24小時溫度曲線繪制elif num == 2:hum_curve(data1,city_name) #相對濕度曲線繪制elif num == 3:air_curve(data1,city_name) #空氣質(zhì)量曲線繪制elif num == 4:tem_curve14(data14, city_name) # 15天溫度曲線繪制elif num == 5:wind_radar(data14, city_name) # 風向雷達圖elif num == 6:weather_pie(data14, city_name) # 繪制天氣餅圖else:print("查詢結(jié)束...")return Falseif __name__ == '__main__':main()這算是我第一次真正意義上自己獨立完成的python程序,做下來還是比較興奮的,同時還有許多想法,比如加個scrapy框架,再搞個pyqt5的gui,讓這個程序更加完美,可惜現(xiàn)在的知識儲備不足,所以暫時只能做這么多。這也是我發(fā)布的第一篇csdn,以后編程中遇到的,收獲的,我都會繼續(xù)在csdn發(fā)布?
總結(jié)
以上是生活随笔為你收集整理的Python天气查询系统(连接数据库版)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Netty心跳机制-长连接
- 下一篇: 电子政务网-网络架构