|
@@ -5,16 +5,29 @@ from typing import Dict
|
|
|
from urllib.parse import parse_qs, urlparse
|
|
from urllib.parse import parse_qs, urlparse
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
+def _extract_query_param(content_url: str | None, param: str) -> str | None:
|
|
|
|
|
+ """从 URL query 中提取指定参数值"""
|
|
|
|
|
+ if not content_url:
|
|
|
|
|
+ return None
|
|
|
|
|
+ query = urlparse(content_url).query
|
|
|
|
|
+ return parse_qs(query).get(param, [None])[0]
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
def extract_wx_sn(content_url: str | None) -> str | None:
|
|
def extract_wx_sn(content_url: str | None) -> str | None:
|
|
|
"""从文章 URL 中提取 sn 参数作为 wx_sn
|
|
"""从文章 URL 中提取 sn 参数作为 wx_sn
|
|
|
|
|
|
|
|
文章链接格式: http://mp.weixin.qq.com/s?__biz=...&sn=xxx...
|
|
文章链接格式: http://mp.weixin.qq.com/s?__biz=...&sn=xxx...
|
|
|
sn 参数值即为微信文章链接 ID。
|
|
sn 参数值即为微信文章链接 ID。
|
|
|
"""
|
|
"""
|
|
|
- if not content_url:
|
|
|
|
|
- return None
|
|
|
|
|
- query = urlparse(content_url).query
|
|
|
|
|
- return parse_qs(query).get("sn", [None])[0]
|
|
|
|
|
|
|
+ return _extract_query_param(content_url, "sn")
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+def extract_biz(content_url: str | None) -> str | None:
|
|
|
|
|
+ """从文章 URL 中提取 __biz 参数,标识公众号主体
|
|
|
|
|
+
|
|
|
|
|
+ 文章链接格式: http://mp.weixin.qq.com/s?__biz=MzIxNDE5NDA2OQ==&sn=xxx...
|
|
|
|
|
+ """
|
|
|
|
|
+ return _extract_query_param(content_url, "__biz")
|
|
|
|
|
|
|
|
|
|
|
|
|
# 无效搜索词集合 — 仅包含无意义的占位符
|
|
# 无效搜索词集合 — 仅包含无意义的占位符
|
|
@@ -51,6 +64,7 @@ def parse_search_result(
|
|
|
"search_cursor": page,
|
|
"search_cursor": page,
|
|
|
"url": article_url,
|
|
"url": article_url,
|
|
|
"wx_sn": extract_wx_sn(article_url) or "",
|
|
"wx_sn": extract_wx_sn(article_url) or "",
|
|
|
|
|
+ "biz": extract_biz(article_url) or "",
|
|
|
"title": article.get("title", ""),
|
|
"title": article.get("title", ""),
|
|
|
"cover_url": article.get("cover_url", ""),
|
|
"cover_url": article.get("cover_url", ""),
|
|
|
"publish_time": publish_time,
|
|
"publish_time": publish_time,
|
|
@@ -86,11 +100,10 @@ def parse_detail(detail: Dict) -> Dict:
|
|
|
"video_url_list": detail.get("video_url_list") or [],
|
|
"video_url_list": detail.get("video_url_list") or [],
|
|
|
"is_cache": 1 if detail.get("is_cache") else 0,
|
|
"is_cache": 1 if detail.get("is_cache") else 0,
|
|
|
"extra": {
|
|
"extra": {
|
|
|
- "biz_info": detail.get("biz_info"),
|
|
|
|
|
"item_index": detail.get("item_index"),
|
|
"item_index": detail.get("item_index"),
|
|
|
"channel_account_name": detail.get("channel_account_name"),
|
|
"channel_account_name": detail.get("channel_account_name"),
|
|
|
},
|
|
},
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
-__all__ = ["extract_wx_sn", "is_valid_keyword", "parse_search_result", "parse_detail"]
|
|
|
|
|
|
|
+__all__ = ["extract_wx_sn", "extract_biz", "is_valid_keyword", "parse_search_result", "parse_detail"]
|