fix(wechat): switch search from miku_ai to Exa, upgrade to tier 0 (#233)

miku_ai (Sogou WeChat search) has been unmaintained for 20 months.
Exa can search AND read WeChat articles via mp.weixin.qq.com domain
filtering — verified: search returns articles, crawling returns full text.
Jina Reader fails on WeChat (CAPTCHA block).

- wechat.py: check() now detects Exa (primary) + Camoufox (optional)
- tier downgraded from 2 to 0 (Exa is zero-config)
- skill/references/web.md: updated WeChat commands to use Exa
- 104 tests passing

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Pnant
2026-03-31 15:57:54 +08:00
committed by GitHub
parent 21214fd02a
commit 6548a50824
2 changed files with 47 additions and 42 deletions
+33 -27
View File
@@ -1,8 +1,8 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
"""WeChat Official Account articles — read and search. """WeChat Official Account articles — read and search.
Read: wechat-article-for-ai (Camoufox stealth browser) Read: Exa crawling (primary) / Camoufox stealth browser (optional)
Search: miku_ai (Sogou WeChat search) Search: Exa web_search with includeDomains mp.weixin.qq.com
""" """
import shutil import shutil
@@ -10,11 +10,25 @@ import subprocess
from .base import Channel from .base import Channel
def _exa_available() -> bool:
mcporter = shutil.which("mcporter")
if not mcporter:
return False
try:
r = subprocess.run(
[mcporter, "config", "list"],
capture_output=True, text=True, timeout=5,
)
return "exa" in r.stdout.lower()
except Exception:
return False
class WeChatChannel(Channel): class WeChatChannel(Channel):
name = "wechat" name = "wechat"
description = "微信公众号文章" description = "微信公众号文章"
backends = ["wechat-article-for-ai (Camoufox)", "miku_ai (搜狗搜索)"] backends = ["Exa via mcporter (搜索+阅读)", "Camoufox (可选阅读)"]
tier = 2 tier = 0
def can_handle(self, url: str) -> bool: def can_handle(self, url: str) -> bool:
from urllib.parse import urlparse from urllib.parse import urlparse
@@ -22,36 +36,28 @@ class WeChatChannel(Channel):
return "mp.weixin.qq.com" in d or "weixin.qq.com" in d return "mp.weixin.qq.com" in d or "weixin.qq.com" in d
def check(self, config=None): def check(self, config=None):
has_read = False has_exa = _exa_available()
has_search = False has_camoufox = False
try: try:
import camoufox # noqa: F401 import camoufox # noqa: F401
has_read = True has_camoufox = True
except ImportError: except ImportError:
pass pass
try: if has_exa and has_camoufox:
import miku_ai # noqa: F401 return "ok", "完整可用(Exa 搜索 + Exa/Camoufox 阅读公众号文章)"
has_search = True elif has_exa:
except ImportError: return "ok", (
pass "通过 Exa 搜索和阅读微信公众号文章(免费,无需额外配置)。"
"可选安装 Camoufox 获得更好的全文阅读效果。"
if has_read and has_search: )
return "ok", "完整可用(搜索 + 阅读公众号文章)" elif has_camoufox:
elif has_read:
return "ok", "可阅读公众号文章(URL → Markdown)。安装 miku_ai 可解锁搜索:pip install miku_ai"
elif has_search:
return "warn", ( return "warn", (
"可搜索公众号文章但无法阅读全文。安装阅读工具:\n" "Camoufox 可阅读公众号文章,但搜索功能需要 Exa。"
" pip install camoufox[geoip] markdownify beautifulsoup4 httpx mcp" "运行 `agent-reach install --env=auto` 安装 Exa。"
) )
else: else:
return "off", ( return "off", (
"需要安装微信公众号工具:\n" "需要 mcporter + Exa MCP 来搜索和阅读微信公众号文章。\n"
" # 阅读(URL → Markdown):\n" "运行 `agent-reach install --env=auto` 安装。"
" pip install camoufox[geoip] markdownify beautifulsoup4 httpx mcp\n"
" # 搜索(关键词 → 文章列表):\n"
" pip install miku_ai\n"
" 详见 https://github.com/bzd6661/wechat-article-for-ai"
) )
+14 -15
View File
@@ -31,28 +31,27 @@ mcporter call 'web-reader.webReader(url: "https://example.com", return_format: "
## 微信公众号 / WeChat Articles ## 微信公众号 / WeChat Articles
**注意**: 微信公众号文章无法用 Jina Reader 或 curl 直接读取,必须使用专用工具。 ### 搜索公众号文章(通过 Exa)
### 搜索文章 (miku_ai) ```bash
# 搜索微信公众号文章
```python mcporter call 'exa.web_search_exa(query: "搜索关键词", numResults: 5, includeDomains: ["mp.weixin.qq.com"])'
python3 -c "
import asyncio
from miku_ai import get_wexin_article
async def s():
for a in await get_wexin_article('query', 5):
print(f'{a[\"title\"]} | {a[\"url\"]}')
asyncio.run(s())
"
``` ```
### 读取文章 (Camoufox - 绕过微信反爬) ### 阅读公众号文章全文(通过 Exa
```bash
# 抓取文章全文
mcporter call 'exa.crawling_exa(urls: ["https://mp.weixin.qq.com/s/ARTICLE_ID"], maxCharacters: 10000)'
```
### 可选:Camoufox 阅读(反爬更强)
```bash ```bash
cd ~/.agent-reach/tools/wechat-article-for-ai && python3 main.py "https://mp.weixin.qq.com/s/ARTICLE_ID" cd ~/.agent-reach/tools/wechat-article-for-ai && python3 main.py "https://mp.weixin.qq.com/s/ARTICLE_ID"
``` ```
> **重要**: 微信文章必须用 Camoufox 读取,其他方法会失败 > **注意**: Jina Reader 无法读取微信文章(被 CAPTCHA 拦截),推荐用 Exa
## RSS (feedparser) ## RSS (feedparser)
@@ -72,6 +71,6 @@ for e in feedparser.parse('FEED_URL').entries[:5]:
|-----|---------| |-----|---------|
| 通用网页 | Jina Reader (`curl r.jina.ai`) | | 通用网页 | Jina Reader (`curl r.jina.ai`) |
| 需要图片/格式控制 | web-reader MCP | | 需要图片/格式控制 | web-reader MCP |
| 微信公众号 | Camoufox (读取) + miku_ai (搜索) | | 微信公众号 | Exa (搜索+阅读) / Camoufox (可选阅读) |
| RSS 订阅 | feedparser | | RSS 订阅 | feedparser |
| 微博/知乎等 | Jina Reader | | 微博/知乎等 | Jina Reader |