用python寫一個簡單的天氣查詢腳本

數據來自中國天氣網

廢話不多說,先看下效果
在這裏插入圖片描述
在這裏插入圖片描述

代碼解析

先導入一些要用到的模塊

import requests
import json
import sys
from bs4 import BeautifulSoup

通過的城市名獲取一個存有相關地點的json文件

在這裏插入圖片描述
在這裏插入圖片描述
通過開發者工具中可以看到,每當輸入框中的內容發生變化的時候,瀏覽器都會發送一個get請求,服務器收到這個請求後返回了一個json文件,這個文件存有與輸入地名相關的一些地名和對應的編號,圖1紅色框中的數據就是來自這裏。我們用requests,get的方法模擬瀏覽器發送這個請求拿到這個json數據稍做處理

# 將輸入的 地名 轉化 爲存有相關地點數據的json數據
def cityNameToJsonData(_cityname):
    url = "http://toy1.weather.com.cn/search"
    _params = {'cityname': _cityname, 'callback': "success_jsonpCallback"}
    headers = {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0'; 'Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36"}
    resp = requests.get(url, params=_params, headers=headers)
    resp.encoding = 'utf-8'
    strdata = resp.text.split('(')[1][:-1]
    JsonData = json.loads(strdata)
    return JsonData

把json數據中的地名展示出來,供使用者二次選擇

上面說過了,這個json文件中不僅有相關地點的名字,還有對應的id,我們可以暫時先把相關地名都print出來,通過輸入地名序號的方法確定目標地點的id(模擬在瀏覽器中點擊了輸入框的彈出選項)

# 把json數據中的相關地名展示出來,進行二次選擇 確定查詢目標 返回目標地點的id
def getId(jsonData):
    cityInfo = []
    for data in jsonData:
        # ['101010100', 'beijing', '北京', 'Beijing', '北京', 'Beijing', '10', '100000', 'BJ', '北京']
        temp = data["ref"].split("~")
        # '101010100'
        _id = temp[0]
        # '北京-北京-北京'
        cityName = temp[9] + "-" + temp[4] + "-" + temp[2]
        cityInfo.append([_id, cityName])
    print("\n請輸入下列地名前的序號再次確定:")
    for index in range(len(cityInfo)):
        print(str(index + 1) + ": " + cityInfo[index][1])
    cityNo = int(input())
    while cityNo < 1 or cityNo > len(cityInfo):
        cityNo = int(input("編號有誤,請重新輸入\n"))
    return cityInfo[cityNo - 1][0]

通過上面獲得的id,查詢該地區近一週的天氣情況

我們隨便查詢一個地方的天氣就可以發現,展示某地區天氣的網址爲:
http://www.weather.com.cn/weather/cityId.shtml
cityId爲對應地區的id。
例如:
北京近七天的天氣情況:http://www.weather.com.cn/weather/101010100.shtml
但是經過測試發現一些id長度大於9的地區的天氣網址格式爲:
http://forecast.weather.com.cn/town/weathern/cityId.shtml
例如:
河南嵩縣大坪村近七天的天氣情況爲:http://forecast.weather.com.cn/town/weathern/101180907004.shtml
推測應該是縣級以下單位採用第二種方法(沒有過多測試),因此我們根據id的長度不同分兩種方法來獲取城市的天氣情況,由於網頁的佈局也是不同的,所以要對兩種長度的id分開處理,當然,處理過程還是差不多的(用requests.get獲取到網頁的html文件,用BeautifulSoup進行一下解析,最後再對數據進行一下篩選與字符串的處理)

def getCityWeaInfoById(cityId):
    if len(cityId) <= 9:
        url = "http://www.weather.com.cn/weather/%s.shtml" % cityId
        resp = requests.get(url)
        resp.encoding = 'utf-8'
        soup = BeautifulSoup(resp.text, 'lxml')
        weaDiv = soup.find('ul', class_="t")
        day_weaDiv = weaDiv.find_all('li')
        for div in day_weaDiv:
            date = div.find('h1').text
            wea = div.find('p', class_="wea").text
            tem = div.find('p', class_="tem").text
            winDiv = div.find('p', 'win')
            win = ""
            for span in winDiv.find_all('span'):
                win += span['title'] + " "
            win += winDiv.find('i').text.split(';')[-1]
            # 空格
            print()
            print(date)
            print(wea)
            print(tem)
            print(win)
            print("-----------------------------------------------------")
    else:
        url = "http://forecast.weather.com.cn/town/weathern/%s.shtml" % cityId
        resp = requests.get(url)
        resp.encoding = 'utf-8'
        soup = BeautifulSoup(resp.text, 'lxml')
        temdiv = soup.find('div', class_="blueFor-container")
        js = temdiv.find('script')
        eventDay = js.text.split('[')[-2].replace('"', '').split(']')[0]
        eventEight = js.text.split('[')[-1].replace('"', '').split(']')[0]
        eventDay = eventDay.split(',')
        eventEight = eventEight.split(',')
        dateDiv = soup.find('ul', class_="date-container").find_all('li')
        dateList = []
        for div in dateDiv:
            date = div.find('p', class_="date").text
            date_info = div.find('p', class_="date-info").text
            dateList.append([date, date_info])
        weaDiv = soup.find('ul', class_="blue-container")
        wea = []
        for div in weaDiv.find_all('li', class_="blue-item"):
            weather_info = div.find('p', class_="weather-info").text.replace(" ", '').strip()
            win_info = div.find_all('i', class_='wind-icon')[0]['title'] + "  " + div.find_all('i', class_='wind-icon')[
                0]['title'] + " " + div.find('p', class_='wind-info').text.strip()
            wea.append(weather_info+"\n"+win_info)
        for index in range(len(dateList)):
            # 空格
            print()
            print(dateList[index][0]+"  "+dateList[index][1])
            print(eventDay[index]+"℃/"+eventEight[index]+"℃")
            print(wea[index])
            print("--------------------------------------------------------------")

最後在爲我們的程序寫個簡單的入口

if __name__ == '__main__':
    cmd = 1
    while cmd:
        cityName = input("\n輸入城市、鄉鎮、街道、景點名稱 查天氣:\n")
        jsonData = cityNameToJsonData(cityName)
        if len(jsonData) == 0:
            print("抱歉未查詢到數據。請確認地名無誤並嘗試重新輸入\n")
            continue
        cityId = getId(jsonData)
        getCityWeaInfoById(cityId)
        cmd = int(input("輸入0退出程序,輸入1繼續查詢\n\n"))

更多源碼

發佈了17 篇原創文章 · 獲贊 27 · 訪問量 2625
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章