parsehub 2.1.0__tar.gz → 2.1.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. {parsehub-2.1.0/src/parsehub.egg-info → parsehub-2.1.2}/PKG-INFO +40 -22
  2. {parsehub-2.1.0 → parsehub-2.1.2}/README.md +39 -21
  3. {parsehub-2.1.0 → parsehub-2.1.2}/pyproject.toml +1 -1
  4. parsehub-2.1.2/src/parsehub/parsers/parser/zhihu.py +64 -0
  5. {parsehub-2.1.0 → parsehub-2.1.2}/src/parsehub/provider_api/coolapk.py +2 -0
  6. {parsehub-2.1.0 → parsehub-2.1.2}/src/parsehub/provider_api/xhs.py +2 -2
  7. parsehub-2.1.2/src/parsehub/provider_api/zhihu.py +748 -0
  8. {parsehub-2.1.0 → parsehub-2.1.2}/src/parsehub/types/platform.py +1 -0
  9. {parsehub-2.1.0 → parsehub-2.1.2}/src/parsehub/types/result.py +1 -1
  10. {parsehub-2.1.0 → parsehub-2.1.2/src/parsehub.egg-info}/PKG-INFO +40 -22
  11. {parsehub-2.1.0 → parsehub-2.1.2}/src/parsehub.egg-info/SOURCES.txt +2 -0
  12. {parsehub-2.1.0 → parsehub-2.1.2}/test/test_core_offline.py +6 -0
  13. {parsehub-2.1.0 → parsehub-2.1.2}/LICENSE +0 -0
  14. {parsehub-2.1.0 → parsehub-2.1.2}/setup.cfg +0 -0
  15. {parsehub-2.1.0 → parsehub-2.1.2}/src/__init__.py +0 -0
  16. {parsehub-2.1.0 → parsehub-2.1.2}/src/parsehub/__init__.py +0 -0
  17. {parsehub-2.1.0 → parsehub-2.1.2}/src/parsehub/cli.py +0 -0
  18. {parsehub-2.1.0 → parsehub-2.1.2}/src/parsehub/cli_config.py +0 -0
  19. {parsehub-2.1.0 → parsehub-2.1.2}/src/parsehub/config/__init__.py +0 -0
  20. {parsehub-2.1.0 → parsehub-2.1.2}/src/parsehub/config/config.py +0 -0
  21. {parsehub-2.1.0 → parsehub-2.1.2}/src/parsehub/errors.py +0 -0
  22. {parsehub-2.1.0 → parsehub-2.1.2}/src/parsehub/parsers/__init__.py +0 -0
  23. {parsehub-2.1.0 → parsehub-2.1.2}/src/parsehub/parsers/base/__init__.py +0 -0
  24. {parsehub-2.1.0 → parsehub-2.1.2}/src/parsehub/parsers/base/base.py +0 -0
  25. {parsehub-2.1.0 → parsehub-2.1.2}/src/parsehub/parsers/base/ytdlp.py +0 -0
  26. {parsehub-2.1.0 → parsehub-2.1.2}/src/parsehub/parsers/parser/__init__.py +0 -0
  27. {parsehub-2.1.0 → parsehub-2.1.2}/src/parsehub/parsers/parser/bilibili.py +0 -0
  28. {parsehub-2.1.0 → parsehub-2.1.2}/src/parsehub/parsers/parser/coolapk.py +0 -0
  29. {parsehub-2.1.0 → parsehub-2.1.2}/src/parsehub/parsers/parser/douyin.py +0 -0
  30. {parsehub-2.1.0 → parsehub-2.1.2}/src/parsehub/parsers/parser/facebook.py +0 -0
  31. {parsehub-2.1.0 → parsehub-2.1.2}/src/parsehub/parsers/parser/instagram.py +0 -0
  32. {parsehub-2.1.0 → parsehub-2.1.2}/src/parsehub/parsers/parser/kuaishou.py +0 -0
  33. {parsehub-2.1.0 → parsehub-2.1.2}/src/parsehub/parsers/parser/pipix.py +0 -0
  34. {parsehub-2.1.0 → parsehub-2.1.2}/src/parsehub/parsers/parser/snapchat.py +0 -0
  35. {parsehub-2.1.0 → parsehub-2.1.2}/src/parsehub/parsers/parser/threads.py +0 -0
  36. {parsehub-2.1.0 → parsehub-2.1.2}/src/parsehub/parsers/parser/tieba.py +0 -0
  37. {parsehub-2.1.0 → parsehub-2.1.2}/src/parsehub/parsers/parser/tiktok.py +0 -0
  38. {parsehub-2.1.0 → parsehub-2.1.2}/src/parsehub/parsers/parser/twitter.py +0 -0
  39. {parsehub-2.1.0 → parsehub-2.1.2}/src/parsehub/parsers/parser/weibo.py +0 -0
  40. {parsehub-2.1.0 → parsehub-2.1.2}/src/parsehub/parsers/parser/weixin.py +0 -0
  41. {parsehub-2.1.0 → parsehub-2.1.2}/src/parsehub/parsers/parser/xhs.py +0 -0
  42. {parsehub-2.1.0 → parsehub-2.1.2}/src/parsehub/parsers/parser/xiaoheihe.py +0 -0
  43. {parsehub-2.1.0 → parsehub-2.1.2}/src/parsehub/parsers/parser/youtube.py +0 -0
  44. {parsehub-2.1.0 → parsehub-2.1.2}/src/parsehub/parsers/parser/zuiyou.py +0 -0
  45. {parsehub-2.1.0 → parsehub-2.1.2}/src/parsehub/provider_api/__init__.py +0 -0
  46. {parsehub-2.1.0 → parsehub-2.1.2}/src/parsehub/provider_api/bilibili.py +0 -0
  47. {parsehub-2.1.0 → parsehub-2.1.2}/src/parsehub/provider_api/douyin.py +0 -0
  48. {parsehub-2.1.0 → parsehub-2.1.2}/src/parsehub/provider_api/instagram.py +0 -0
  49. {parsehub-2.1.0 → parsehub-2.1.2}/src/parsehub/provider_api/kuaishou.py +0 -0
  50. {parsehub-2.1.0 → parsehub-2.1.2}/src/parsehub/provider_api/pipix.py +0 -0
  51. {parsehub-2.1.0 → parsehub-2.1.2}/src/parsehub/provider_api/threads.py +0 -0
  52. {parsehub-2.1.0 → parsehub-2.1.2}/src/parsehub/provider_api/tieba.py +0 -0
  53. {parsehub-2.1.0 → parsehub-2.1.2}/src/parsehub/provider_api/tiktok.py +0 -0
  54. {parsehub-2.1.0 → parsehub-2.1.2}/src/parsehub/provider_api/twitter.py +0 -0
  55. {parsehub-2.1.0 → parsehub-2.1.2}/src/parsehub/provider_api/weibo.py +0 -0
  56. {parsehub-2.1.0 → parsehub-2.1.2}/src/parsehub/provider_api/weixin.py +0 -0
  57. {parsehub-2.1.0 → parsehub-2.1.2}/src/parsehub/provider_api/xiaoheihe.py +0 -0
  58. {parsehub-2.1.0 → parsehub-2.1.2}/src/parsehub/provider_api/zuiyou.py +0 -0
  59. {parsehub-2.1.0 → parsehub-2.1.2}/src/parsehub/types/__init__.py +0 -0
  60. {parsehub-2.1.0 → parsehub-2.1.2}/src/parsehub/types/callback.py +0 -0
  61. {parsehub-2.1.0 → parsehub-2.1.2}/src/parsehub/types/media_file.py +0 -0
  62. {parsehub-2.1.0 → parsehub-2.1.2}/src/parsehub/types/media_ref.py +0 -0
  63. {parsehub-2.1.0 → parsehub-2.1.2}/src/parsehub/types/post.py +0 -0
  64. {parsehub-2.1.0 → parsehub-2.1.2}/src/parsehub/utils/downloader.py +0 -0
  65. {parsehub-2.1.0 → parsehub-2.1.2}/src/parsehub/utils/helpers.py +0 -0
  66. {parsehub-2.1.0 → parsehub-2.1.2}/src/parsehub/utils/media_info.py +0 -0
  67. {parsehub-2.1.0 → parsehub-2.1.2}/src/parsehub.egg-info/dependency_links.txt +0 -0
  68. {parsehub-2.1.0 → parsehub-2.1.2}/src/parsehub.egg-info/entry_points.txt +0 -0
  69. {parsehub-2.1.0 → parsehub-2.1.2}/src/parsehub.egg-info/requires.txt +0 -0
  70. {parsehub-2.1.0 → parsehub-2.1.2}/src/parsehub.egg-info/top_level.txt +0 -0
  71. {parsehub-2.1.0 → parsehub-2.1.2}/test/test_cli.py +0 -0
  72. {parsehub-2.1.0 → parsehub-2.1.2}/test/test_cli_config.py +0 -0
  73. {parsehub-2.1.0 → parsehub-2.1.2}/test/test_downloader.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: parsehub
3
- Version: 2.1.0
3
+ Version: 2.1.2
4
4
  Summary: 轻量、异步、开箱即用的社交媒体聚合解析库
5
5
  Author-email: 梓澪 <zilingmio@gmail.com>
6
6
  License: MIT
@@ -70,26 +70,27 @@ Dynamic: license-file
70
70
 
71
71
  ## 🌐 支持平台
72
72
 
73
- | 平台 | 视频 | 图文 | 其他 |
74
- |-----------------|:--:|:--:|------|
75
- | **Twitter / X** | ✅ | ✅ | 📝 文章 |
76
- | **Instagram** | ✅ | ✅ | |
77
- | **YouTube** | ✅ | | 🎵 音乐 |
78
- | **Facebook** | ✅ | | |
79
- | **Threads** | ✅ | ✅ | |
80
- | **Bilibili** | ✅ | | 📝 动态 |
81
- | **抖音** | ✅ | ✅ | ☀️日常 |
82
- | **TikTok** | ✅ | ✅ | |
83
- | **微博** | ✅ | ✅ | |
84
- | **小红书** | ✅ | ✅ | |
85
- | **贴吧** | ✅ | ✅ | |
86
- | **微信公众号** | | ✅ | |
87
- | **快手** | ✅ | | |
88
- | **酷安** | | ✅ | |
89
- | **皮皮虾** | ✅ | ✅ | |
90
- | **最右** | ✅ | ✅ | |
91
- | **小黑盒** | ✅ | ✅ | |
92
- | **Snapchat** | ✅ | | |
73
+ | 平台 | 视频 | 图文 | 其他 |
74
+ |-----------------|:--:|:--:|---------------|
75
+ | **Twitter / X** | ✅ | ✅ | 📝 文章 |
76
+ | **Instagram** | ✅ | ✅ | |
77
+ | **YouTube** | ✅ | | 🎵 音乐 |
78
+ | **Facebook** | ✅ | | |
79
+ | **Threads** | ✅ | ✅ | |
80
+ | **Bilibili** | ✅ | | 📝 动态 |
81
+ | **抖音** | ✅ | ✅ | ☀️日常 |
82
+ | **TikTok** | ✅ | ✅ | |
83
+ | **微博** | ✅ | ✅ | |
84
+ | **小红书** | ✅ | ✅ | |
85
+ | **贴吧** | ✅ | ✅ | |
86
+ | **微信公众号** | | ✅ | |
87
+ | **快手** | ✅ | | |
88
+ | **酷安** | | ✅ | |
89
+ | **皮皮虾** | ✅ | ✅ | |
90
+ | **最右** | ✅ | ✅ | |
91
+ | **小黑盒** | ✅ | ✅ | |
92
+ | **Snapchat** | ✅ | | |
93
+ | **知乎** | ✅ | ✅ | 🐶 问答, 专栏, 圈子 |
93
94
 
94
95
  ## 📦 安装
95
96
 
@@ -210,6 +211,7 @@ print(result)
210
211
  - `TikTok`
211
212
  - `快手`
212
213
  - `小红书`
214
+ - `知乎`
213
215
 
214
216
  ```python
215
217
  from parsehub import ParseHub
@@ -308,6 +310,21 @@ except ParseError as exc:
308
310
 
309
311
  ---
310
312
 
313
+ ## 🤝 参与贡献
314
+
315
+ 欢迎提交 Pull Request 或 Issue!
316
+
317
+ - Bug 反馈请附上相关 URL 和日志信息
318
+
319
+ ### 开发规范
320
+
321
+ 提交代码前请至少执行:
322
+
323
+ ```bash
324
+ ruff format && ruff check --fix && uv run mypy
325
+ uv run pytest
326
+ ```
327
+
311
328
  ## 🤝 参考项目
312
329
 
313
330
  - [Evil0ctal/Douyin_TikTok_Download_API](https://github.com/Evil0ctal/Douyin_TikTok_Download_API)
@@ -315,10 +332,11 @@ except ParseError as exc:
315
332
  - [instaloader/instaloader](https://github.com/instaloader/instaloader)
316
333
  - [SocialSisterYi/bilibili-API-collect](https://github.com/SocialSisterYi/bilibili-API-collect)
317
334
  - [Nemo2011/bilibili-api](https://github.com/Nemo2011/bilibili-api)
335
+ - [cv-cat/ZhihuApis](https://github.com/cv-cat/ZhihuApis)
318
336
 
319
337
  ## 📜 开源协议
320
338
 
321
- 本项目基于 [MIT License](LICENSE) 开源。
339
+ 本项目基于 [MIT License](LICENSE) 开源
322
340
 
323
341
  ---
324
342
 
@@ -28,26 +28,27 @@
28
28
 
29
29
  ## 🌐 支持平台
30
30
 
31
- | 平台 | 视频 | 图文 | 其他 |
32
- |-----------------|:--:|:--:|------|
33
- | **Twitter / X** | ✅ | ✅ | 📝 文章 |
34
- | **Instagram** | ✅ | ✅ | |
35
- | **YouTube** | ✅ | | 🎵 音乐 |
36
- | **Facebook** | ✅ | | |
37
- | **Threads** | ✅ | ✅ | |
38
- | **Bilibili** | ✅ | | 📝 动态 |
39
- | **抖音** | ✅ | ✅ | ☀️日常 |
40
- | **TikTok** | ✅ | ✅ | |
41
- | **微博** | ✅ | ✅ | |
42
- | **小红书** | ✅ | ✅ | |
43
- | **贴吧** | ✅ | ✅ | |
44
- | **微信公众号** | | ✅ | |
45
- | **快手** | ✅ | | |
46
- | **酷安** | | ✅ | |
47
- | **皮皮虾** | ✅ | ✅ | |
48
- | **最右** | ✅ | ✅ | |
49
- | **小黑盒** | ✅ | ✅ | |
50
- | **Snapchat** | ✅ | | |
31
+ | 平台 | 视频 | 图文 | 其他 |
32
+ |-----------------|:--:|:--:|---------------|
33
+ | **Twitter / X** | ✅ | ✅ | 📝 文章 |
34
+ | **Instagram** | ✅ | ✅ | |
35
+ | **YouTube** | ✅ | | 🎵 音乐 |
36
+ | **Facebook** | ✅ | | |
37
+ | **Threads** | ✅ | ✅ | |
38
+ | **Bilibili** | ✅ | | 📝 动态 |
39
+ | **抖音** | ✅ | ✅ | ☀️日常 |
40
+ | **TikTok** | ✅ | ✅ | |
41
+ | **微博** | ✅ | ✅ | |
42
+ | **小红书** | ✅ | ✅ | |
43
+ | **贴吧** | ✅ | ✅ | |
44
+ | **微信公众号** | | ✅ | |
45
+ | **快手** | ✅ | | |
46
+ | **酷安** | | ✅ | |
47
+ | **皮皮虾** | ✅ | ✅ | |
48
+ | **最右** | ✅ | ✅ | |
49
+ | **小黑盒** | ✅ | ✅ | |
50
+ | **Snapchat** | ✅ | | |
51
+ | **知乎** | ✅ | ✅ | 🐶 问答, 专栏, 圈子 |
51
52
 
52
53
  ## 📦 安装
53
54
 
@@ -168,6 +169,7 @@ print(result)
168
169
  - `TikTok`
169
170
  - `快手`
170
171
  - `小红书`
172
+ - `知乎`
171
173
 
172
174
  ```python
173
175
  from parsehub import ParseHub
@@ -266,6 +268,21 @@ except ParseError as exc:
266
268
 
267
269
  ---
268
270
 
271
+ ## 🤝 参与贡献
272
+
273
+ 欢迎提交 Pull Request 或 Issue!
274
+
275
+ - Bug 反馈请附上相关 URL 和日志信息
276
+
277
+ ### 开发规范
278
+
279
+ 提交代码前请至少执行:
280
+
281
+ ```bash
282
+ ruff format && ruff check --fix && uv run mypy
283
+ uv run pytest
284
+ ```
285
+
269
286
  ## 🤝 参考项目
270
287
 
271
288
  - [Evil0ctal/Douyin_TikTok_Download_API](https://github.com/Evil0ctal/Douyin_TikTok_Download_API)
@@ -273,10 +290,11 @@ except ParseError as exc:
273
290
  - [instaloader/instaloader](https://github.com/instaloader/instaloader)
274
291
  - [SocialSisterYi/bilibili-API-collect](https://github.com/SocialSisterYi/bilibili-API-collect)
275
292
  - [Nemo2011/bilibili-api](https://github.com/Nemo2011/bilibili-api)
293
+ - [cv-cat/ZhihuApis](https://github.com/cv-cat/ZhihuApis)
276
294
 
277
295
  ## 📜 开源协议
278
296
 
279
- 本项目基于 [MIT License](LICENSE) 开源。
297
+ 本项目基于 [MIT License](LICENSE) 开源
280
298
 
281
299
  ---
282
300
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "parsehub"
3
- version = "2.1.0"
3
+ version = "2.1.2"
4
4
  description = "轻量、异步、开箱即用的社交媒体聚合解析库"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.12.0"
@@ -0,0 +1,64 @@
1
+ from ...provider_api.zhihu import ZhihuAPI, ZhihuPin, ZhihuPinType, ZhihuQA, ZhihuZhuanLan
2
+ from ...types import (
3
+ ImageParseResult,
4
+ ImageRef,
5
+ MultimediaParseResult,
6
+ Platform,
7
+ RichTextParseResult,
8
+ VideoParseResult,
9
+ VideoRef,
10
+ )
11
+ from ..base.base import BaseParser
12
+
13
+
14
+ class ZhihuParser(BaseParser):
15
+ __platform__ = Platform.ZHIHU
16
+ __supported_type__ = ["问答", "专栏", "圈子"]
17
+ __match__ = r"^(http(s)?://)?(www|zhuanlan).zhihu.com/(pin|question|p)/.*"
18
+
19
+ async def _do_parse(
20
+ self, raw_url: str
21
+ ) -> RichTextParseResult | MultimediaParseResult | ImageParseResult | VideoParseResult:
22
+ if not (c := self.cookie.get_value()):
23
+ raise ValueError("知乎需要配置已登录的 Cookie")
24
+ result = await ZhihuAPI(cookie=c, proxy=self.proxy).parse(raw_url)
25
+ match result:
26
+ case ZhihuQA():
27
+ if not result.markdown_answer:
28
+ return MultimediaParseResult(title=result.question)
29
+ return RichTextParseResult(
30
+ title=result.question,
31
+ media=[ImageRef(url=i) for i in result.imgs],
32
+ markdown_content=result.markdown_answer,
33
+ )
34
+ case ZhihuZhuanLan():
35
+ return RichTextParseResult(
36
+ title=result.title,
37
+ markdown_content=result.markdown_content,
38
+ media=[ImageRef(url=i) for i in result.imgs],
39
+ )
40
+ case ZhihuPin():
41
+ match result.type:
42
+ case ZhihuPinType.TEXT:
43
+ return ImageParseResult(title=result.title, content=result.plaintext_content)
44
+ case ZhihuPinType.IMAGE:
45
+ return ImageParseResult(
46
+ title=result.title,
47
+ content=result.plaintext_content,
48
+ photo=[
49
+ ImageRef(url=i.url, thumb_url=i.thumb_url, width=i.width, height=i.height)
50
+ for i in result.media
51
+ ],
52
+ )
53
+ case ZhihuPinType.VIDEO:
54
+ v = result.media[0]
55
+ return VideoParseResult(
56
+ title=result.title,
57
+ content=result.plaintext_content,
58
+ video=VideoRef(
59
+ url=v.url, thumb_url=v.thumb_url, height=v.height, width=v.width, duration=v.duration
60
+ ),
61
+ )
62
+
63
+
64
+ __all__ = ["ZhihuParser"]
@@ -25,6 +25,8 @@ class Coolapk:
25
25
  if title_element and (title := title_element.text.strip()):
26
26
  content = soup.find(class_="feed-article-message")
27
27
  if content is None:
28
+ if "s=" in url or "shareKey=" in url:
29
+ raise ValueError("获取内容失败")
28
30
  raise ValueError("获取内容失败, 分享时请保留 shareKey 或 s 参数")
29
31
  markdown_content = MarkdownConverter(heading_style="ATX").convert(str(content))
30
32
  text_content = "".join(BeautifulSoup(markdown(markdown_content), "lxml").find_all(string=True))
@@ -122,7 +122,7 @@ class XHSAPI:
122
122
 
123
123
  @staticmethod
124
124
  def get_trace_id(img_url: str) -> str:
125
- match = re.search(r"/(spectrum|note_pre_post_uhdr|notes_pre_post|notes_uhdr)/([^/!]+)(?:!.*)?$", img_url)
125
+ match = re.search(r"/[a-f0-9]{32}/(.*)/([^/!]+)(?:!.*)?", img_url)
126
126
  if match:
127
127
  return f"{match.group(1)}/{match.group(2)}"
128
128
 
@@ -169,7 +169,7 @@ class XHSPost:
169
169
  if __name__ == "__main__":
170
170
 
171
171
  async def main() -> None:
172
- url = "https://www.xiaohongshu.com/explore/68fe2018000000000303a844?xsec_token=ABgAb-5vt3L-aTqeEjdxJP_ylf02hY5n2f-y75yMQWrUo=&xsec_source=pc_search&source=web_explore_feed"
172
+ url = ""
173
173
  xhs = XHSAPI()
174
174
  print(await xhs.extract(url))
175
175