Collect WeChat public account articles via RSSHub and publish to Feishu Docs. Includes RSS mirror discovery, deduplication, markdown generation, and automated cron scheduling.
Collect WeChat public account articles via RSSHub and publish to Feishu Docs. Includes RSS mirror discovery, deduplication, markdown generation, and automated cron scheduling.
# Normal run (today's articles only)
python3 ~/wechat_collector.py
# Test mode (3 articles per account)
python3 ~/wechat_collector.py --all
# Local only (no Feishu)
python3 ~/wechat_collector.py --no-feishu
# Specific date
python3 ~/wechat_collector.py --date 2026-04-11
Pitfalls
RSSHub timeouts: Public instances block; use mirrors or add delays between requests
RSSHub route deprecation: As of 2026-04-11, the following routes return NotFound errors on tested mirrors (pseudoyu.com, rssforever.com, rsshub.app):
Fallback when RSS unavailable: Use local history file as fallback:
HISTORY_FILE = Path.home() / "wechat_articles" / ".history.json"# Parse history file for today's articles when RSSHub fails
Feishu 400 errors: App permissions need republishing in Feishu Developer Console
Wiki permission denied: App must be added to Wiki space members with "Can Edit" permission
Error: permission denied: wiki space permission denied, tenant needs edit permission
Fix: Wiki Settings → Member Management → Add App → Grant Edit Permission
Date parsing: GMT dates need conversion to local time
Content writing: Docx block API is complex; documents created empty by default
chat_id format: P2P and Group chat_ids both start with oc_, distinguish by context
History stale: Clear .history.json if reprocessing needed
RSS feed content: Some routes return summary only; use feeddd route for full content (when available)
Working Example Configuration
# Account RSS mapping (verified working as of 2026-04-11)
ACCOUNTS = {
"Draco正在VibeCoding": "https://rsshub.app/wechat/mp/wx_zbus_xcbmtyn/Draco_Daily",
"AI寒武纪": "https://rsshub.app/wechat/mp/wx_zbus_xcbmtyn/AI_himao",
"左岸AI": "https://rsshub.app/wechat/mp/wx_zbus_xcbmtyn/leftbankai",
"老金带你玩AI": "https://rsshub.app/wechat/mp/wx_zbus_xcbmtyn/wlaixkj"
}
# Notification targets
FEISHU_CHAT_ID = "oc_f9135e7516510373d91fed5756d62d7d"# P2P with Ningyao
TELEGRAM_CHAT_ID = "813280132"# Your Telegram chat ID# Cron schedule# 0 9 * * * /usr/bin/python3 /path/to/wechat_collector.py >> /var/log/wechat.log 2>&1
Fallback Strategies When RSS Fails
Option 1: Browser Automation (Recommended for Single Articles)
When web_extract returns "Unauthorized" for WeChat MP URLs (common as of 2026-04-11), use browser automation:
# Step 1: Navigate to article
browser_navigate(url="https://mp.weixin.qq.com/s/xxxxx")
# Step 2: Get full content as accessible tree
browser_snapshot(full=True)
# Returns parsed structure with headings, paragraphs, lists# Step 3: Convert to markdown and save locally# Title is in heading level 1# Author is typically in text after "原创" or first text node# Content follows paragraph structure
Key findings from 2026-04-11:
WeChat MP articles are heavily protected against direct HTTP fetch
web_extract consistently fails with "Unauthorized: Invalid token"
Browser automation with stealth features works reliably
Content structure: heading[1] = title, following paragraphs = author/date, then body content
Option 2: History File Parsing
When RSSHub sources are unavailable, extract articles from local history:
from pathlib import Path
import json
defextract_from_history(target_date: str = None):
'''Extract today's articles from history file when RSS fails'''from datetime import datetime
target_date = target_date or datetime.now().strftime("%Y-%m-%d")
history_file = Path.home() / "wechat_articles" / ".history.json"ifnot history_file.exists():
return []
withopen(history_file, 'r', encoding='utf-8') as f:
history = json.load(f)
articles = []
for link, info in history.items():
if info.get('date') == target_date:
articles.append({
'source': info.get('source'),
'title': info.get('title'),
'link': link,
'date': target_date
})
return articles
# Usage when RSSHub fails
articles = extract_from_history("2026-04-11")
for article in articles:
print(f"{article['source']}|{article['link']}")
Manual Article Archiving Workflow
When user provides a single WeChat article URL for immediate archiving:
Try web_extract first (fastest)
If succeeds: use extracted markdown content
If fails with 401/Unauthorized: proceed to browser
Browser fallback (when extract fails)
browser_navigate(url=article_url)
snapshot = browser_snapshot(full=True)
# Parse snapshot['snapshot'] for content tree# Extract: title (heading level 1), author (first text node), date (emphasis/em), body (paragraphs)
Save locally
output_path = f"~/wechat_articles/YYYY-MM-DD_{source}_{title}.md"# Write markdown with metadata header
Upload to Feishu
# Create document
doc = create_doc(token, title=f"[{source}] {title}")
doc_id = doc['data']['document']['document_id']
# Add content block (CRITICAL: use integer block_type, not string)
add_block(token, doc_id, block_id, content, block_type=2) # 2 = text
File Locations
Main script: ~/wechat_collector.py
Feishu module: ~/feishu_docs_uploader.py
Output: ~/wechat_articles/YYYY-MM-DD/
History: ~/.wechat_articles/.history.json
Logs: /var/log/wechat_collector.log (when using cron)