wechat-media-writer 2.2.8 → 2.2.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/SKILL.md CHANGED
@@ -140,7 +140,7 @@ Token 缓存在 `~/.wechat/token_cache.json`(自动管理,2小时有效期
140
140
 
141
141
  <!-- 主题配图(第一张图,使用主题贴图,非书籍原图) -->
142
142
  <p style="margin:0 0 20px;text-align:center;">
143
- <img src="{THEME_IMG_1}" style="width:100%;max-width:600px;display:block;margin:0 auto;border-radius:4px;" alt="主题配图" />
143
+ <img src="{THEME_IMG_1}" style="width:100%;max-width:600px;display:block;margin:0 auto;border-radius:4px;" alt="" />
144
144
  </p>
145
145
 
146
146
  <!-- 章节(无数字编号,直接标题) -->
@@ -153,7 +153,7 @@ Token 缓存在 `~/.wechat/token_cache.json`(自动管理,2小时有效期
153
153
 
154
154
  <!-- 主题配图(章节间穿插,与文风统一) -->
155
155
  <p style="margin:0 0 20px;text-align:center;">
156
- <img src="{THEME_IMG_2}" style="width:100%;max-width:600px;display:block;margin:0 auto;border-radius:4px;" alt="主题配图" />
156
+ <img src="{THEME_IMG_2}" style="width:100%;max-width:600px;display:block;margin:0 auto;border-radius:4px;" alt="" />
157
157
  </p>
158
158
 
159
159
  <!-- 金句引用块(圆角浅背景,无左侧竖条) -->
@@ -170,7 +170,7 @@ Token 缓存在 `~/.wechat/token_cache.json`(自动管理,2小时有效期
170
170
 
171
171
  <!-- 主题配图(章节中段) -->
172
172
  <p style="margin:0 0 20px;text-align:center;">
173
- <img src="{THEME_IMG_3}" style="width:100%;max-width:600px;display:block;margin:0 auto;border-radius:4px;" alt="主题配图" />
173
+ <img src="{THEME_IMG_3}" style="width:100%;max-width:600px;display:block;margin:0 auto;border-radius:4px;" alt="" />
174
174
  </p>
175
175
 
176
176
  <!-- 分隔符(章节之间) -->
@@ -383,7 +383,7 @@ python3 scripts/publish.py --title "标题" --content-file content.html --cover-
383
383
 
384
384
  <!-- 结尾页(与正文风格延续,使用主题色) -->
385
385
  <p style="margin:0 0 16px;text-align:center;">
386
- <img src="{THEME_IMG_END}" style="width:100%;max-width:600px;display:block;margin:0 auto;border-radius:4px;" alt="主题配图" />
386
+ <img src="{THEME_IMG_END}" style="width:100%;max-width:600px;display:block;margin:0 auto;border-radius:4px;" alt="" />
387
387
  </p>
388
388
 
389
389
  <p style="font-size:14px;color:#ccc;text-align:center;letter-spacing:8px;margin:24px 0 16px;">· · · · · ·</p>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wechat-media-writer",
3
- "version": "2.2.8",
3
+ "version": "2.2.9",
4
4
  "description": "微信公众号书评、影评文章自动生成与发布 - Skill",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -61,7 +61,7 @@ HTML = f"""<section style="margin:0;padding:0 0 48px;font-family:-apple-system,B
61
61
 
62
62
  <!-- 主题配图1(头部) -->
63
63
  <p style="margin:0 0 20px;text-align:center;">
64
- <img src="{THEME_IMG_1}" style="width:100%;max-width:600px;display:block;margin:0 auto;border-radius:4px;" alt="主题配图"/>
64
+ <img src="{THEME_IMG_1}" style="width:100%;max-width:600px;display:block;margin:0 auto;border-radius:4px;" alt=""/>
65
65
  </p>
66
66
 
67
67
  <!-- 先搞懂写书的这个人 -->
@@ -74,7 +74,7 @@ HTML = f"""<section style="margin:0;padding:0 0 48px;font-family:-apple-system,B
74
74
 
75
75
  <!-- 主题配图2(先搞懂写书的这个人后) -->
76
76
  <p style="margin:0 0 20px;text-align:center;">
77
- <img src="{THEME_IMG_2}" style="width:100%;max-width:600px;display:block;margin:0 auto;border-radius:4px;" alt="主题配图"/>
77
+ <img src="{THEME_IMG_2}" style="width:100%;max-width:600px;display:block;margin:0 auto;border-radius:4px;" alt=""/>
78
78
  </p>
79
79
 
80
80
  <!-- 金句引用块(圆角浅背景,无左侧竖条) -->
@@ -92,7 +92,7 @@ HTML = f"""<section style="margin:0;padding:0 0 48px;font-family:-apple-system,B
92
92
 
93
93
  <!-- 主题配图3(逻辑导图后) -->
94
94
  <p style="margin:0 0 20px;text-align:center;">
95
- <img src="{THEME_IMG_3}" style="width:100%;max-width:600px;display:block;margin:0 auto;border-radius:4px;" alt="主题配图"/>
95
+ <img src="{THEME_IMG_3}" style="width:100%;max-width:600px;display:block;margin:0 auto;border-radius:4px;" alt=""/>
96
96
  </p>
97
97
 
98
98
  <!-- 三个颠覆认知的真相 -->
@@ -111,7 +111,7 @@ HTML = f"""<section style="margin:0;padding:0 0 48px;font-family:-apple-system,B
111
111
 
112
112
  <!-- 主题配图4(论点后) -->
113
113
  <p style="margin:0 0 20px;text-align:center;">
114
- <img src="{THEME_IMG_4}" style="width:100%;max-width:600px;display:block;margin:0 auto;border-radius:4px;" alt="主题配图"/>
114
+ <img src="{THEME_IMG_4}" style="width:100%;max-width:600px;display:block;margin:0 auto;border-radius:4px;" alt=""/>
115
115
  </p>
116
116
 
117
117
  <!-- 这本书的短板,不吐不快 -->
@@ -137,7 +137,7 @@ HTML = f"""<section style="margin:0;padding:0 0 48px;font-family:-apple-system,B
137
137
 
138
138
  <!-- 主题配图5(读完真正留下的东西后) -->
139
139
  <p style="margin:0 0 20px;text-align:center;">
140
- <img src="{THEME_IMG_5}" style="width:100%;max-width:600px;display:block;margin:0 auto;border-radius:4px;" alt="主题配图"/>
140
+ <img src="{THEME_IMG_5}" style="width:100%;max-width:600px;display:block;margin:0 auto;border-radius:4px;" alt=""/>
141
141
  </p>
142
142
 
143
143
  <!-- 四条拿来就用的行动项 -->
@@ -195,7 +195,7 @@ HTML = f"""<section style="margin:0;padding:0 0 48px;font-family:-apple-system,B
195
195
 
196
196
  <!-- 结尾页:主题配图 + 书名 + 作者 + 核心总结 -->
197
197
  <p style="margin:0 0 16px;text-align:center;">
198
- <img src="{THEME_IMG_END}" style="width:100%;max-width:600px;display:block;margin:0 auto;border-radius:4px;" alt="主题配图"/>
198
+ <img src="{THEME_IMG_END}" style="width:100%;max-width:600px;display:block;margin:0 auto;border-radius:4px;" alt=""/>
199
199
  </p>
200
200
 
201
201
  <p style="font-size:14px;color:#ccc;text-align:center;letter-spacing:8px;margin:24px 0 16px;">· · · · · ·</p>
@@ -74,22 +74,35 @@ THEME_CANDIDATES = {
74
74
  }
75
75
 
76
76
 
77
- def download_image(url, output_path):
78
- """下载图片到指定路径"""
77
+ def download_image(url, output_path, retries=3, retry_delay=1):
78
+ """下载图片到指定路径,带重试机制"""
79
+ import time
80
+
79
81
  ctx = ssl.create_default_context()
80
82
  ctx.check_hostname = False
81
83
  ctx.verify_mode = ssl.CERT_NONE
82
84
 
83
85
  req = urllib.request.Request(url, headers={"User-Agent": "Mozilla/5.0"})
84
- try:
85
- data = urllib.request.urlopen(req, context=ctx, timeout=15).read()
86
- os.makedirs(os.path.dirname(output_path), exist_ok=True)
87
- with open(output_path, "wb") as f:
88
- f.write(data)
89
- return True
90
- except Exception as e:
91
- print(f"下载失败: {e}")
92
- return False
86
+ os.makedirs(os.path.dirname(output_path), exist_ok=True)
87
+
88
+ for attempt in range(1, retries + 1):
89
+ try:
90
+ data = urllib.request.urlopen(req, context=ctx, timeout=20).read()
91
+ # 验证下载到的是真实图片(> 5KB 且 magic bytes 正确)
92
+ if len(data) < 5000:
93
+ raise ValueError(f"下载文件过小: {len(data)} bytes")
94
+ if not data[:3] in (b"\xff\xd8\xff", b"\x89PN", b"GIF"):
95
+ raise ValueError(f"非图片格式: {data[:8]!r}")
96
+ with open(output_path, "wb") as f:
97
+ f.write(data)
98
+ return True
99
+ except Exception as e:
100
+ if attempt < retries:
101
+ time.sleep(retry_delay * attempt)
102
+ continue
103
+ print(f"下载失败(重试 {retries} 次后放弃): {e}")
104
+ return False
105
+ return False
93
106
 
94
107
 
95
108
  def download_pexels_image(pid, output_path, w=1200):
@@ -154,12 +167,14 @@ def aesthetics_score(image_path):
154
167
  def download_theme_images(theme, output_dir, count=6):
155
168
  """根据主题下载多张精美图片
156
169
 
157
- 自动跳过 404/失败候选,下载到临时文件名,再按美学评分重命名为 img_1.jpg ~ img_N.jpg
170
+ 自动跳过 404/失败候选(带 3 次重试),下载到临时文件名,
171
+ 再按美学评分重命名为 img_1.jpg ~ img_N.jpg
158
172
  返回: 已下载图片路径列表(按美学评分降序)
159
173
  """
160
174
  os.makedirs(output_dir, exist_ok=True)
161
175
  candidates = THEME_CANDIDATES.get(theme, THEME_CANDIDATES["books"])
162
176
  downloaded = [] # 临时文件列表
177
+ failed_pids = []
163
178
 
164
179
  # 1) 全部下载到临时文件
165
180
  for i, pid in enumerate(candidates):
@@ -168,8 +183,13 @@ def download_theme_images(theme, output_dir, count=6):
168
183
  tmp_path = os.path.join(output_dir, f"_tmp_{theme}_{i}_{pid}.jpg")
169
184
  if download_pexels_image(pid, tmp_path):
170
185
  downloaded.append(tmp_path)
186
+ else:
187
+ failed_pids.append(pid)
171
188
 
189
+ if failed_pids:
190
+ print(f" ⚠️ 候选 {failed_pids} 下载失败(共 {len(failed_pids)} 张)")
172
191
  if not downloaded:
192
+ print(f" ❌ 主题 {theme} 所有候选图下载失败")
173
193
  return []
174
194
 
175
195
  # 2) 按美学评分排序
@@ -40,7 +40,13 @@ def ensure_theme_images(cover_dir, theme="books", count=6):
40
40
  return
41
41
 
42
42
  print(f"主题插图不足,自动下载 {count} 张(主题: {theme})...")
43
- download_theme_images(theme, cover_dir, count)
43
+ result = download_theme_images(theme, cover_dir, count)
44
+
45
+ if len(result) < count:
46
+ print(
47
+ f"⚠️ 实际下载 {len(result)}/{count} 张,建议换其他主题或重试",
48
+ file=sys.stderr,
49
+ )
44
50
 
45
51
 
46
52
  def ensure_cover_image(cover_dir):