diff --git a/utils/markdown_to_image.py b/utils/markdown_to_image.py index 7fd62b4..81c0fa1 100644 --- a/utils/markdown_to_image.py +++ b/utils/markdown_to_image.py @@ -3,6 +3,10 @@ from playwright.async_api import async_playwright import os import asyncio +def playwright_browser_installed(): + """检查 Playwright 的 Chromium 浏览器是否已安装""" + chromium_path = os.path.expanduser("~/.cache/ms-playwright/chromium") + return os.path.exists(chromium_path) # linux 下需要安装字体 # sudo apt-get install -y fonts-noto-cjk fonts-noto-cjk-extra # sudo apt-get install -y fonts-noto-color-emoji fonts-noto-cjk fonts-wqy-microhei @@ -164,44 +168,34 @@ async def html_to_image(html_file, output_image): """ try: async with async_playwright() as p: - # 检查系统类型 - if os.name == 'nt': # Windows + # Windows 系统 + if os.name == 'nt': possible_chrome_paths = [ r"C:\Users\Liu_WIN10\AppData\Local\Google\Chrome\Application\chrome.exe", r"C:\Users\Liu-OPEN\AppData\Local\Google\Chrome\Application\chrome.exe", r"C:\Program Files\Google\Chrome\Application\chrome.exe", r"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" ] - browser_path = None - for path in possible_chrome_paths: - if os.path.exists(path): - browser_path = path - print(f"找到浏览器路径: {browser_path}") - break + browser_path = next((p for p in possible_chrome_paths if os.path.exists(p)), None) if browser_path: + print(f"找到浏览器路径: {browser_path}") browser = await p.chromium.launch(executable_path=browser_path) else: - print("未找到指定的Chrome浏览器路径,尝试使用默认浏览器") - # 尝试安装 Playwright 浏览器 - try: + print("未找到 Chrome,尝试使用 Playwright 自带浏览器") + if not playwright_browser_installed(): + print("Playwright 浏览器未安装,正在安装...") import subprocess - print("正在安装 Playwright 浏览器...") - subprocess.run(["playwright", "install"], check=True) - print("Playwright 浏览器安装完成") - except Exception as install_error: - print(f"安装 Playwright 浏览器失败: {install_error}") + subprocess.run(["playwright", "install", "chromium"], check=True) + print("安装完成") browser = await p.chromium.launch() - else: # Linux - try: - # 尝试安装 Playwright 浏览器 + else: + if not playwright_browser_installed(): + print("Playwright 浏览器未安装,正在安装...") import subprocess - print("正在安装 Playwright 浏览器...") - subprocess.run(["playwright", "install"], check=True) - print("Playwright 浏览器安装完成") - except Exception as install_error: - print(f"安装 Playwright 浏览器失败: {install_error}") + subprocess.run(["playwright", "install", "chromium"], check=True) + print("安装完成") browser = await p.chromium.launch() - + page = await browser.new_page() await page.goto(f'file://{os.path.abspath(html_file)}') await page.set_viewport_size({"width": 750, "height": 800}) @@ -230,53 +224,6 @@ async def convert_md_str_to_image(md_content, output_image): # 示例使用 if __name__ == "__main__": # 示例 Markdown 字符串(包含中文和 Emoji) - md_content = """ -# 🌟「4KED康复训练群 - 2023年3月26日 总结」🌟 - -## 📊 今日数据快报 -- **总消息数**:📩 165 条 -- **最活跃时段**:🔥 11:00 - 12:00 (📈 25 条/小时) -- **聊天时段**:🕒 09:41 - 16:40 - -## 🌌 话题总结 - -### 1️⃣ 【开源OA项目讨论】 ⭐⭐⭐⭐⭐ -🕒 **聊天时段**:09:42 - 09:54 (👥 5 人参与) -🔍 **话题回顾**: -本次讨论围绕 **开源OA项目** 展开,大家探讨目前市场上有哪些可选的项目。啧啧,用户们的热情高涨,啊菜提出想要了解免费OA项目的需求,水牛和刘政则分享了过往的经验,认为如今的开源项目越来越少,比起大厂的项目,很多选择都不够灵活。通过这样的讨论,群友们互相支招,真是一场“技术头脑风暴”! -> **金句回顾**:"真是心血来潮,搞OA不是小事!" —— [@啊菜] -📌 **额外信息**:讨论中提及了 **开源OA项目的网站链接**,有兴趣的可以去看看! - -### 2️⃣ 【智能医疗AI的落地方向】 ⭐⭐⭐⭐ -🕒 **聊天时段**:10:29 - 10:39 (👥 7 人参与) -🔍 **高能讨论**: -在这一话题中,用户们讨论了 **医疗行业中AI大模型落地的方向**。纯洁善良互助有爱提出了医疗知识库和对话式AI的想法,引发了其他用户的热烈回响,纷纷分享了智能问诊、病例解析等方向。大家的参与热情可见一斑,兴致勃勃讨论未来的医学科技趋势! -> **精华总结**:"基层干事的人最懂需求!" —— [@纯洁善良互助有爱] - -### 3️⃣ 【趣谈工作与生活】 ⭐⭐⭐ -🕒 **聊天时段**:10:00 - 11:00 (👥 8 人参与) -🔍 **讨论亮点**: -在轻松愉快的氛围中,用户们围绕工作和生活进行了有趣的讨论,尤其是关于“带薪休假”的轻松话题,大家分享了自己的工作经验和休闲方式。水牛和刘政重返了一个“带薪拉屎”的幽默梗,令群聊气氛瞬间活跃,友好的互动让人忍俊不禁! - -### 4️⃣ 【电子产品的讨论】 ⭐⭐⭐ -🕒 **聊天时段**:12:00 - 14:00 (👥 6 人参与) -🔍 **精彩瞬间**: -此话题围绕 **近期电子产品和技术讨论** 展开,参与者们活跃分享各自对电子产品的见解。用户们聊天中不乏对新技术的吐槽与调侃,《特斯拉在美国被砸事件》等话题也层出不穷,是一个技术与笑点并存的轻松话题! -> **幽默补充**:"这不是数字经济,就是电子的ED!" —— [@水牛] - -### 5️⃣ 【现实生活和社会现象】 ⭐⭐⭐ -🕒 **聊天时段**:14:30 - 16:25 (👥 7 人参与) -🔍 **讨论小结**: -用户们在沉着交谈的同时,关注了现实生活中的社会现象。“开车的礼仪”、“不买卖积分”等成为了热门话题,刘政和Y.Shuang的告诫触发了共鸣,引发参与者们对生活中各种现象的探讨与反思,令人深思。 - -## 🎖️ 今日荣誉榜 -🏆 **群聊 MVP**:[@水牛] -👑 **获奖理由**: -✅ 发起多个热门话题 -✅ 贡献多种幽默段子 -✅ **金句输出**:"带薪拉屎,太美了!" - -✨ *本总结由 AI 自动生成,快来看看你今天是不是最靓的崽!🔥* - """ + md_content = """### Python的类型\n1. **数字类型**:\n - **整数(int)**:用于表示整数,例如`5`、`-10`。在Python 3中,整数的长度不受限制,可以表示任意大小的整数。\n - **浮点数(float)**:用于表示带有小数部分的数字,例如`3.14`、`-0.5`。它采用IEEE 754标准来存储,可能会存在精度问题。\n - **复数(complex)**:由实数部分和虚数部分组成,例如`3 + 4j`,其中`j`表示虚数单位。\n2. **序列类型**:\n - **字符串(str)**:用于表示文本,是不可变的字符序列,例如`'Hello, World!'`、`\"Python\"`。可以通过索引和切片操作访问其中的字符。\n - **列表(list)**:是可变的有序序列,可以包含不同类型的元素,例如`[1, 'apple', 3.14]`。支持添加、删除、修改元素等操作。\n - **元组(tuple)**:与列表类似,但它是不可变的有序序列,例如`(1, 'apple', 3.14)`。一旦创建,其元素不能被修改。\n3. **映射类型**:\n - **字典(dict)**:是一种无序的键值对集合,用于存储和检索数据,例如`{'name': 'Alice', 'age': 25}`。键必须是唯一且不可变的,值可以是任意类型。\n4. **集合类型**:\n - **集合(set)**:是一个无序的不重复元素集合,例如`{1, 2, 3}`。常用于去重和数学集合运算,如并集、交集、差集等。\n - **冻结集合(frozenset)**:与集合类似,但它是不可变的,一旦创建就不能修改。\n\n### 将时间戳转换为str\n在Python中,可以使用`datetime`模块来完成时间戳转换为字符串的操作。以下是示例代码:\n\n```python\nimport datetime\n\n\n# 假设时间戳为秒级时间戳\ntimestamp = 1672531200\n# 将时间戳转换为datetime对象\ndt = datetime.datetime.fromtimestamp(timestamp)\n# 将datetime对象格式化为字符串\nstr_time = dt.strftime('%Y-%m-%d %H:%M:%S')\nprint(str_time)\n```\n\n在上述代码中:\n1. `import datetime`导入`datetime`模块。\n2. `datetime.datetime.fromtimestamp(timestamp)`将时间戳(这里假设为秒级时间戳)转换为`datetime`对象。\n3. `dt.strftime('%Y-%m-%d %H:%M:%S')`使用`strftime`方法将`datetime`对象格式化为指定格式的字符串,`%Y`表示四位数的年份,`%m`表示两位数的月份,`%d`表示两位数的日期,`%H`表示24小时制的小时,`%M`表示分钟,`%S`表示秒。\n\n如果时间戳是毫秒级的,需要先将其转换为秒级,例如:\n\n```python\nimport datetime\n\n\n# 假设时间戳为毫秒级时间戳\ntimestamp = 1672531200000\n# 将毫秒级时间戳转换为秒级\ntimestamp_seconds = timestamp / 1000\n# 将时间戳转换为datetime对象\ndt = datetime.datetime.fromtimestamp(timestamp_seconds)\n# 将datetime对象格式化为字符串\nstr_time = dt.strftime('%Y-%m-%d %H:%M:%S')\nprint(str_time)\n""" spath = asyncio.run(convert_md_str_to_image(md_content, "output.png")) print(spath) \ No newline at end of file