python爬虫天气预报

import os
import random
import csv
import locale
import requests
from bs4 import BeautifulSoup
from datetime import timedelta, date
from utils import make_user_agent

import matplotlib.pyplot as plt


class WeatherPredictCrawler:
    locale.setlocale(locale.LC_TIME, 'zh_CN')
    plt.rcParams['font.family'] = ['sans-serif']
    plt.rcParams['font.sans-serif'] = ['SimSun']

    def __init__(self, city: str, path: str, day: int = 30, SAVE_CSV=True, SAVE_FIG=True, SHOW_WEATHER=True):
        self.base_url = "https://www.tianqi.com/"
        self.city = city
        self.path = path
        self.day = day

        self.SAVE_CSV = SAVE_CSV
        self.SAVE_FIG = SAVE_FIG
        self.SHOW_WEATHER = SHOW_WEATHER

        self.dates = [date.today() + i * timedelta(days=1) for i in range(31)]
        self.weather_s = []
        self.save_path = f"{self.path}//{self.city}{self.dates[0]}到{self.dates[-1]}"

    def create_csv(self):
        with open(self.save_path + ".csv", "w", newline="") as f:
            writer = csv.writer(f)
            writer.writerow(["日期", "星期", "天气", "最高温", "最低温", "空气", "风向", "风级"])

    def save_data(self, data):
        if self.SAVE_CSV:
            with open(self.save_path + ".csv", "a", newline="") as f:
                writer = csv.writer(f)
                writer.writerow(data)

    def draw_fig(self):
        plt.figure(figsize=(12, 8))
        plt.xlabel('日期')
        plt.xticks(rotation=90)
        plt.ylabel('温度')
        plt.title(f"{self.city} {self.day}天内气温")
        ax = plt.subplot()
        ax.spines['bottom'].set_position(('data', 0))  # x轴设为0基准
        days = [i[0] for i in self.weather_s]
        max_ts = [i[3] for i in self.weather_s]
        min_ts = [i[4] for i in self.weather_s]
        w_s = [i[2] for i in self.weather_s]
        plt.plot(days, max_ts, '-', label='最高温', color='red', linewidth=1.0)
        plt.plot(days, min_ts, '-', label='最低温', color='blue', linewidth=1.0)

        if self.SHOW_WEATHER:
            plt.scatter(days, max_ts, s=10)
            for i in range(len(days)):
                y = max_ts[i]
                yp = y
                if i > 1:
                    yp = max_ts[i - 1]
                if y >= yp:
                    c = random.randint(2, 6)
                    c /= 10
                else:
                    c = random.randint(2, 6)
                    c /= -10
                r = random.randint(0, 180)
                g = random.randint(0, 180)
                b = random.randint(0, 180)
                color = '#{:02x}{:02x}{:02x}'.format(r, g, b)
                plt.text(days[i], max_ts[i] + c, w_s[i], fontsize=10, color=color,
                         verticalalignment="center",
                         horizontalalignment="center"
                         )
        plt.legend(loc=2)
        plt.savefig(self.save_path + ".png", dpi=300)

    def request_url(self, url):
        headers = make_user_agent()
        response = requests.get(url, headers=headers).text
        resp = response.replace('<!--', '').replace('-->', '')  # 有看到隐藏了空气状况
        self.handle_request(resp)

    def handle_request(self, resp):
        soup = BeautifulSoup(resp, "html.parser")
        weaul = soup.find("ul", attrs={"class": "weaul"})
        day_weathers = weaul.find_all("li")

        for i in range(len(day_weathers)):
            data = day_weathers[i].text.split("\n")
            unique_lst = [x for i, x in enumerate(data) if x not in data[:i]]
            data = unique_lst[1:]
            # ['01-25', '今天', '晴', '-2~7℃', '空气 优', '西风 1级', '查看天气详情']
            day = self.dates[i]
            week = self.dates[i].strftime("%A")
            weather = data[2]
            t = data[3].split("℃")[0]
            min_t = int(t.split("~")[0])
            max_t = int(t.split("~")[1])
            if len(data) == 6:
                air = ""
                wind = ""
                wind_l = ""
            else:
                air = data[4].split(" ")[1]
                wind = data[5].split(" ")[0]
                wind_l = data[5].split(" ")[1]
            # ["日期", "星期", "天气", "最高温", "最低温", "空气", "风向", "风级"]
            row_data = [day, week, weather, max_t, min_t, air, wind, wind_l]
            self.weather_s.append(row_data)
            self.save_data(row_data)

    def run(self):
        url = self.base_url + '/' + self.city + '/' + str(self.day) + "/"
        os.makedirs(self.path) if not os.path.exists(self.path) else None
        self.create_csv() if self.SAVE_CSV else None
        # print(url)
        self.request_url(url)
        self.draw_fig() if self.SAVE_FIG else None


if __name__ == '__main__':
    weather_p = WeatherPredictCrawler('hefei', 'weather')
    weather_p.run()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值