文章目录
本节使用的是某du天气 https://weathernew.pae.baidu.com/weathernew/pc
💖分析网站🌈
⛅目标:获取当前 温度,天气,风向风力
🔬分析
先来看下重庆天气,我们可以看到地址栏传入了两个参数query=重庆天气
和srcid=4982
第一个很好办,只需要城市名字就行了。
对于第二个参数,我们打开北京和广州的页面,发现srcid不变,那这就好解决了
用postman尝试请求一下
看到这里
window.tplData = {
"logo":{"url":"https:\/\/www.baidu.com\/"},
"weather":{
"bodytemp_info":"\u6e7f\u5ea6\u5927\uff0c\u4f53\u611f\u6e7f\u51c9",
"wind_direction":"\u897f\u5317\u98ce",
"site":"mlogcn",
"weather":"\u96fe",
"dew_temperature":"14",
"precipitation_type":"\u65e0\u964d\u96e8\u548c\u964d\u96ea",
"wind_direction_num":"7",
"temperature":"17",
"wind_power":"2\u7ea7",
...
}
...
}
将其中的Unicode解码:
window.tplData = {
"logo":{"url":"https:\/\/www.baidu.com\/"},
"weather":{
"bodytemp_info":"湿度大,体感湿凉",
"wind_direction":"西北风",
"site":"mlogcn",
"weather":"雾",
"dew_temperature":"14",
"precipitation_type":"无降雨和降雪",
"wind_direction_num":"7",
"temperature":"17",
"wind_power":"2级",
...
}
...
}
啊哈,对上了。所以我们需要的数据就明确了
- wind_direction
- weather
- temperature
- wind_power
💻Coding with 🧡
🔎获取数据
注意可能get不完全,但对于此例子够用了
头文件:
import requests
import re
import json
requests用来爬数据,re和json都是拿来处理数据的
下面获取网页
def getData(city):
url = "https://weathernew.pae.baidu.com/weathernew/pc"
header = {"user-agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36 Edg/107.0.1418.56"}
query = city + "天气"
param = {"query":query,"srcid":"4982"}
response = requests.get(url,params=param,headers=header).text
这个函数我们传入要获取的城市名,url为目标地址,header是来伪装爬虫的,param为参数。
使用正则表达式从js中将其分离出来:
temperature_u = re.match( r".*\"temperature\":\"(.*?)\",", response).group(1)
weather_u = re.match( r".*\"weather\":\"(.*?)\",", response).group(1)
wind_direction_u = re.match( r".*\"wind_direction\":\"(.*?)\",", response).group(1)
wind_power_u = re.match( r".*\"wind_power\":\"(.*?)\",", response).group(1)
这里我们会遇到一个问题就是获取的数据为Unicode字符串。
因此我们还需一个函数对其进行转换
def u2cc(str): #Unicode to Chinese Character
return json.loads('"%s"' %str)
此部分完整代码:
import requests
import re
import json
def u2cc(str): #Unicode to Chinese Character
return json.loads('"%s"' %str)
def getData(city):
url = "https://weathernew.pae.baidu.com/weathernew/pc"
header = {"user-agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36 Edg/107.0.1418.56"}
query = city + "天气"
param = {"query":query,"srcid":"4982"}
response = requests.get(url,params=param,headers=header).text
#get unicode data
temperature_u = re.match( r"^.*\"temperature\":\"(.*?)\",", response).group(1)
weather_u = re.match( r"^.*\"weather\":\"(.*?)\",", response).group(1)
wind_direction_u = re.match( r"^.*\"wind_direction\":\"(.*?)\",", response).group(1)
wind_power_u = re.match( r"^.*\"wind_power\":\"(.*?)\",", response).group(1)
return [u2cc(temperature_u),u2cc(weather_u),u2cc(wind_direction_u),u2cc(wind_power_u)]
测试一下:
if __name__ == "__main__":
print(getData("重庆"))
肥肠的完美👍
🌊添加GUI
这里用到的是tkinter,并且引入了多线程
import requests
import re
import json
from tkinter import *
from PIL import Image,ImageTk
from threading import Thread
from queue import Queue
import time
全局队列,用于线程之间通信:
exit_code = Queue(1)
data = Queue(1)
🍔App类
class App():
def __init__(self,exit_code,data):
self.win = Tk()
self.win.attributes("-topmost",1)
self.x, self.y = 0, 0
self.win_size = '200x150'
self.win.overrideredirect(True)
self.win.geometry(f"{self.win_size}")
self.canvas = Canvas(width=200, height=150, highlightthickness=0, borderwidth=0)
self.canvas.place(x=0, y=0)
self.bg = PhotoImage(file = "./imgs/1.bg.gif")
self.bg_id = self.canvas.create_image(0, 0, image=self.bg, anchor='nw')
ls_data = data.get()
self.txt_temperature_id=self.canvas.create_text(10,40, font=("Arial", 32),anchor="nw",fill="white")
self.canvas.insert(self.txt_temperature_id,1,ls_data[0]+"℃")
self.txt_weather_id=self.canvas.create_text(120,60, font=("Arial", 16),anchor="nw",fill="white")
self.canvas.insert(self.txt_weather_id,1,ls_data[1])
self.txt_wind_direction_id=self.canvas.create_text(10,110, font=("Arial", 16),anchor="nw",fill="white")
self.canvas.insert(self.txt_wind_direction_id,1,ls_data[2])
self.txt_wind_power_id=self.canvas.create_text(100,110, font=("Arial", 16),anchor="nw",fill="white")
self.canvas.insert(self.txt_wind_power_id,1,ls_data[3])
self.win.bind("<B1-Motion>", self.move)
self.win.bind("<Button-1>", self.get_point)
self.win.bind("<Double-Button-1>", self.close)
def move(self, event):
new_x = (event.x - self.x) + self.win.winfo_x()
new_y = (event.y - self.y) + self.win.winfo_y()
s = f"{self.win_size}+{new_x}+{new_y}"
self.win.geometry(s)
def get_point(self, event):
self.x, self.y = event.x, event.y
def run(self):
self.win.mainloop()
def close(self, event):
self.win.destroy()
exit_code.put("quit")
背景图(呃,确实有一点小粗糙,不过不影响)
⏰更新函数
def data_update_thread(exit_code,data):
data.put(getData("重庆"))
while(exit_code.empty()):
time.sleep(120)#update once per 2 minutes
data.empty()
data.put(getData("重庆"))
🎄最后调用,注册线程
if __name__ == "__main__":
dut = Thread(target=data_update_thread,args=(exit_code,data))
dut.start()
app = App(exit_code,data)
app.run()
🏆最终效果🏆
Python桌面天气效果
🍻完整源码
import requests
import re
import json
from tkinter import *
from PIL import Image,ImageTk
from threading import Thread
from queue import Queue
import time
exit_code = Queue(1)
data = Queue(1)
def u2cc(str): #Unicode to Chinese Character
return json.loads('"%s"' %str)
def getData(city):
url = "https://weathernew.pae.baidu.com/weathernew/pc"
header = {"user-agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36 Edg/107.0.1418.56"}
query = city + "天气"
param = {"query":query,"srcid":"4982"}
response = requests.get(url,params=param,headers=header).text
#get unicode data
temperature_u = re.match( r"^.*\"temperature\":\"(.*?)\",", response).group(1)
weather_u = re.match( r"^.*\"weather\":\"(.*?)\",", response).group(1)
wind_direction_u = re.match( r"^.*\"wind_direction\":\"(.*?)\",", response).group(1)
wind_power_u = re.match( r"^.*\"wind_power\":\"(.*?)\",", response).group(1)
return [u2cc(temperature_u),u2cc(weather_u),u2cc(wind_direction_u),u2cc(wind_power_u)]
def start_move(self, event):
self.x = event.x
self.y = event.y
def stop_move(self, event):
self.x = None
self.y = None
def do_move(self, event):
deltax = event.x - self.x
deltay = event.y - self.y
x = self.winfo_x() + deltax
y = self.winfo_y() + deltay
self.geometry(f"+{x}+{y}")
def data_update_thread(exit_code,data):
data.put(getData("重庆"))
while(exit_code.empty()):
time.sleep(120)#update once per 2 minutes
data.empty()
data.put(getData("重庆"))
class App():
def __init__(self,exit_code,data):
self.win = Tk()
self.win.attributes("-topmost",1)
self.x, self.y = 0, 0
self.win_size = '200x150'
self.win.overrideredirect(True)
self.win.geometry(f"{self.win_size}")
self.canvas = Canvas(width=200, height=150, highlightthickness=0, borderwidth=0)
self.canvas.place(x=0, y=0)
self.bg = PhotoImage(file = "./imgs/1.bg.gif")
self.bg_id = self.canvas.create_image(0, 0, image=self.bg, anchor='nw')
ls_data = data.get()
self.txt_temperature_id=self.canvas.create_text(10,40, font=("Arial", 32),anchor="nw",fill="white")
self.canvas.insert(self.txt_temperature_id,1,ls_data[0]+"℃")
self.txt_weather_id=self.canvas.create_text(120,60, font=("Arial", 16),anchor="nw",fill="white")
self.canvas.insert(self.txt_weather_id,1,ls_data[1])
self.txt_wind_direction_id=self.canvas.create_text(10,110, font=("Arial", 16),anchor="nw",fill="white")
self.canvas.insert(self.txt_wind_direction_id,1,ls_data[2])
self.txt_wind_power_id=self.canvas.create_text(100,110, font=("Arial", 16),anchor="nw",fill="white")
self.canvas.insert(self.txt_wind_power_id,1,ls_data[3])
self.win.bind("<B1-Motion>", self.move)
self.win.bind("<Button-1>", self.get_point)
self.win.bind("<Double-Button-1>", self.close)
def move(self, event):
new_x = (event.x - self.x) + self.win.winfo_x()
new_y = (event.y - self.y) + self.win.winfo_y()
s = f"{self.win_size}+{new_x}+{new_y}"
self.win.geometry(s)
def get_point(self, event):
self.x, self.y = event.x, event.y
def run(self):
self.win.mainloop()
def close(self, event):
self.win.destroy()
exit_code.put("quit")
if __name__ == "__main__":
dut = Thread(target=data_update_thread,args=(exit_code,data))
dut.start()
app = App(exit_code,data)
app.run()