@@ -244,7 +244,7 @@ async def _make_request(self, url: str, retry_on_403: bool = True) -> Dict[str,
244244 response = await session .get (url , headers = headers , timeout = 15 , http_version = http_version )
245245 # HTTP/3 成功,重置失败计数
246246 if self .http3_failed_count > 0 :
247- logger .info (f "✅ HTTP/3 恢复正常,重置失败计数" )
247+ logger .info ("✅ HTTP/3 恢复正常,重置失败计数" )
248248 self .http3_failed_count = 0
249249 except Exception as e :
250250 # HTTP/3 失败,尝试降级到 HTTP/2
@@ -256,7 +256,7 @@ async def _make_request(self, url: str, retry_on_403: bool = True) -> Dict[str,
256256 logger .warning (f"🚫 HTTP/3 连续失败 { self .http3_disable_threshold } 次,切换到 HTTP/2" )
257257
258258 # 降级到 HTTP/2 重试
259- logger .info (f "🔄 降级到 HTTP/2 重试..." )
259+ logger .info ("🔄 降级到 HTTP/2 重试..." )
260260 response = await session .get (url , headers = headers , timeout = 15 )
261261 else :
262262 # 当前浏览器不支持 HTTP/3,直接使用 HTTP/2
@@ -269,7 +269,7 @@ async def _make_request(self, url: str, retry_on_403: bool = True) -> Dict[str,
269269 if response .status_code in (429 , 403 ):
270270 # 403 先尝试轮换浏览器重试,重试失败再设冷却期
271271 if response .status_code == 403 and retry_on_403 and self .rotate_browser :
272- logger .warning (f "⚠️ 收到 403 响应,尝试轮换浏览器重试..." )
272+ logger .warning ("⚠️ 收到 403 响应,尝试轮换浏览器重试..." )
273273 await self ._rotate_browser ()
274274 return await self ._make_request (url , retry_on_403 = False )
275275
@@ -504,7 +504,7 @@ def __init__(self, api_key: str):
504504 async def get_post_by_url (self , url : str ) -> Optional [RedditPost ]:
505505 """通过 URL 获取帖子"""
506506 import httpx
507- from datetime import datetime , timezone
507+ from datetime import datetime
508508
509509 try :
510510 async with httpx .AsyncClient (timeout = 15 ) as client :
@@ -641,6 +641,72 @@ async def get_top_posts(self, subreddit: Optional[str] = None, time_filter: str
641641 async def get_new_posts (self , subreddit : Optional [str ] = None , limit : int = 10 ) -> List [RedditPost ]:
642642 return await self ._get_community_posts (subreddit , "new" , None , limit )
643643
644+ async def get_post_by_id (self , post_id : str ) -> Optional [RedditPost ]:
645+ """通过 ID 获取帖子(构建 permalink 后调用 get_post_by_url)"""
646+ clean_id = post_id .replace ('t3_' , '' )
647+ url = f"https://www.reddit.com/comments/{ clean_id } /"
648+ return await self .get_post_by_url (url )
649+
650+ async def get_comments (self , post_id : str , limit : int = 10 , sort : str = 'top' ) -> List [RedditComment ]:
651+ """通过 post endpoint 获取评论(FetchLayer 返回完整评论树)"""
652+ import httpx
653+ from datetime import datetime
654+
655+ clean_id = post_id .replace ('t3_' , '' )
656+ url = f"https://www.reddit.com/comments/{ clean_id } /"
657+
658+ try :
659+ async with httpx .AsyncClient (timeout = 15 ) as client :
660+ response = await client .post (
661+ f"{ self .BASE_URL } /post" ,
662+ headers = self ._headers ,
663+ json = {"url" : url }
664+ )
665+ response .raise_for_status ()
666+ data = response .json ()
667+
668+ if data .get ("error" ) or data .get ("blocked" ):
669+ logger .error (f"FetchLayer 获取评论失败: { data .get ('error' ) or data .get ('blockReason' )} " )
670+ return []
671+
672+ raw_comments = data .get ("comments" , [])
673+
674+ # 只取顶层评论(depth=0 或 parentFullname 为 None)
675+ top_level = [c for c in raw_comments if c .get ("depth" , 0 ) == 0 or c .get ("parentFullname" ) is None ]
676+
677+ if sort == 'top' :
678+ top_level .sort (key = lambda c : c .get ("score" ) or 0 , reverse = True )
679+
680+ comments = []
681+ for c in top_level [:limit ]:
682+ created_utc = 0.0
683+ created_at = c .get ("createdAt" )
684+ if created_at :
685+ try :
686+ dt = datetime .fromisoformat (created_at .replace ("Z" , "+00:00" ))
687+ created_utc = dt .timestamp ()
688+ except Exception :
689+ pass
690+
691+ body = c .get ("bodyText" , "" )
692+ if not body :
693+ continue
694+
695+ comments .append (RedditComment (
696+ id = c .get ("id" , "" ),
697+ author = c .get ("author" , "[deleted]" ),
698+ body = body ,
699+ score = c .get ("score" ) or 0 ,
700+ created_utc = created_utc ,
701+ ))
702+
703+ logger .info (f"✅ FetchLayer 获取到 { len (comments )} 条评论" )
704+ return comments
705+
706+ except Exception as e :
707+ logger .error (f"FetchLayer 获取评论失败 (post_id={ post_id } ): { e } " )
708+ return []
709+
644710 async def close (self ):
645711 pass
646712
0 commit comments