iShotaBot/defs/weather_graph.py

71 lines
2.1 KiB
Python
Raw Normal View History

2024-09-05 10:47:18 +00:00
import asyncio
import os
import shutil
from pathlib import Path
import aiofiles
import httpx
from bs4 import BeautifulSoup
from defs.bilibili_download import execute
FFMPEG_PATH = "ffmpeg"
URL = "http://www.nmc.cn/publish/satellite/fy4b-visible.htm"
TEMP_PATH = Path("data") / "weather_tmp"
TEMP_PATH.mkdir(exist_ok=True, parents=True)
OUTPUT_PATH = TEMP_PATH / "output.mp4"
class WeatherGraphError(Exception):
def __init__(self, error: str):
self.error = error
async def download_img(client, index: int, url: str):
try:
res = await client.get(url)
if res.status_code != 200:
print(f"下载天气图片失败,错误代码 {res.status_code}")
async with aiofiles.open(
TEMP_PATH / f"img{str(index).zfill(3)}.jpg", "wb"
) as f:
await f.write(res.content)
except Exception as e:
print(f"下载天气图片失败 {url} {e}")
async def get_images():
async with httpx.AsyncClient() as client:
res = await client.get(URL)
if res.status_code != 200:
raise WeatherGraphError(f"获取图片数据失败,错误代码 {res.status_code}")
html = res.content
soup = BeautifulSoup(html, "lxml")
elements = soup.find_all(class_="time")
tasks = []
for index, element in enumerate(reversed(elements)):
url = element["data-img"]
url = url.replace("medium/", "")
task = asyncio.create_task(download_img(client, index, url))
tasks.append(task)
await asyncio.gather(*tasks)
async def get_video():
frame_rate = 6
ffmpeg_cmd = f'{FFMPEG_PATH} -r {frame_rate} -i "{TEMP_PATH}/img%03d.jpg" -vf scale=1920:1080 -c:v libx264 -pix_fmt yuv420p -y "{TEMP_PATH}/output.mp4"'
_, code = await execute(ffmpeg_cmd)
if code != 0:
raise WeatherGraphError("生成视频失败")
async def gen() -> Path:
if not os.path.exists(TEMP_PATH):
os.mkdir(TEMP_PATH)
else:
shutil.rmtree(TEMP_PATH)
os.mkdir(TEMP_PATH)
await get_images()
await get_video()
return OUTPUT_PATH