數據來自中國天氣網
廢話不多說,先看下效果
代碼解析
先導入一些要用到的模塊
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"))