Python爬虫实战(一) ---- 制作自己的桌面天气小工具

请添加图片描述


本节使用的是某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()

🧡项目地址🧡

⭐欢迎Star与Fork⭐

点击下面的图片跳转哟~
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

orbitgw

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值