废话不多说直接扔代码
from flask import Flask, request, send_file
import os
import threading
import atexit
import asyncio
from pyppeteer import launch
from io import BytesIO
import time
from pyecharts import options as opts
from pyecharts.charts import Bar, Grid
# 创建 Flask 应用
app = Flask(__name__)
# 共享浏览器实例和事件循环
browser = None
event_loop = None
async def init_browser():
global browser
# 添加单进程模式和禁用内置退出处理
browser = await launch(
headless=False, # 修改为True,不显浏览器
handleSIGINT=False,
handleSIGTERM=False,
handleSIGHUP=False,
args=[
'--no-sandbox',
'--disable-setuid-sandbox',
'--disable-dev-shm-usage',
'--disable-accelerated-2d-canvas',
'--disable-gpu',
'--single-process' # 添加单进程模式
]
)
def run_event_loop(loop):
asyncio.set_event_loop(loop)
loop.run_forever()
def init_async_resources():
global event_loop
event_loop = asyncio.new_event_loop()
t = threading.Thread(target=run_event_loop, args=(event_loop,), daemon=True)
t.start()
# 在事件循环线程中初始化浏览器
future = asyncio.run_coroutine_threadsafe(init_browser(), event_loop)
future.result() # 等待浏览器初始化完成
@app.route('/screenshot/<name>')
def take_screenshot(name):
url = request.args.get('url', 'https://cn.bing.com/search?q=' + name)
# 将截图任务提交到事件循环线程
future = asyncio.run_coroutine_threadsafe(async_screenshot(url), event_loop)
image_data = future.result()
return send_file(BytesIO(image_data), mimetype='image/png')
async def async_screenshot(html_path):
# 为每个请求创建新的页面实例
page = await browser.newPage()
try:
await page.setViewport({'width': 1920, 'height': 1080})
await page.goto(url, {'waitUntil': 'networkidle2', 'timeout': 30000})
screenshot = await page.screenshot({'fullPage': False}) # fullPage True全页
return screenshot
finally:
await page.close() # 确保关闭页面释放资源
@atexit.register
def shutdown():
if browser:
# 添加延迟关闭确保清理完成
future = asyncio.run_coroutine_threadsafe(browser.close(), event_loop)
try:
future.result(5) # 增加5秒超时
except TimeoutError:
pass
if event_loop:
# 等待事件循环完成剩余任务
event_loop.call_soon_threadsafe(event_loop.stop)
time.sleep(0.5) # 添加短暂延迟
if __name__ == '__main__':
init_async_resources()
app.run(host='0.0.0.0', port=9000, threaded=True)