xiaohongshu.py 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. """Xiaohongshu formal acquisition adapter."""
  2. from __future__ import annotations
  3. from typing import Any
  4. from acquisition.crawler import fetch_post_detail
  5. from acquisition.platforms.base import PlatformCandidate, PlatformItem
  6. from acquisition.search import search_xiaohongshu
  7. from core.config import Settings
  8. class XiaohongshuAdapter:
  9. platform = "xiaohongshu"
  10. def search(
  11. self,
  12. query: str,
  13. *,
  14. settings: Settings,
  15. limit: int,
  16. rate_limiter: Any,
  17. ) -> list[PlatformCandidate]:
  18. rows = search_xiaohongshu(
  19. query,
  20. content_type=settings.search_content_type,
  21. limit=limit,
  22. settings=settings,
  23. rate_limiter=rate_limiter,
  24. )
  25. return [
  26. PlatformCandidate(
  27. rank=i,
  28. platform=self.platform,
  29. source_id=row.get("id") or "",
  30. url=row.get("url") or "",
  31. title=row.get("title") or "",
  32. author=row.get("nick_name") or "",
  33. cover_url=row.get("cover_url") or "",
  34. raw=row,
  35. )
  36. for i, row in enumerate(rows, start=1)
  37. ]
  38. def fetch_detail(
  39. self,
  40. candidate: PlatformCandidate,
  41. *,
  42. settings: Settings,
  43. rate_limiter: Any,
  44. ) -> PlatformItem:
  45. post = fetch_post_detail(
  46. candidate.source_id or candidate.url,
  47. settings=settings,
  48. rate_limiter=rate_limiter,
  49. )
  50. return PlatformItem(
  51. platform=self.platform,
  52. source_id=post.content_id or candidate.source_id,
  53. url=post.url or candidate.url,
  54. content_type=post.content_type or "图文",
  55. title=post.title or candidate.title,
  56. author=post.author_name or candidate.author,
  57. body_text=post.body_text or "",
  58. image_urls=post.image_urls or [candidate.cover_url],
  59. video_urls=post.video_urls,
  60. raw=post.raw if isinstance(post.raw, dict) else {},
  61. )