parsehub 2.3.8__tar.gz → 2.3.9__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.
- {parsehub-2.3.8/src/parsehub.egg-info → parsehub-2.3.9}/PKG-INFO +1 -1
- {parsehub-2.3.8 → parsehub-2.3.9}/pyproject.toml +1 -1
- {parsehub-2.3.8 → parsehub-2.3.9}/src/parsehub/parsers/parser/xiaoheihe.py +18 -2
- {parsehub-2.3.8 → parsehub-2.3.9}/src/parsehub/provider_api/xiaoheihe.py +15 -4
- {parsehub-2.3.8 → parsehub-2.3.9/src/parsehub.egg-info}/PKG-INFO +1 -1
- {parsehub-2.3.8 → parsehub-2.3.9}/LICENSE +0 -0
- {parsehub-2.3.8 → parsehub-2.3.9}/README.md +0 -0
- {parsehub-2.3.8 → parsehub-2.3.9}/setup.cfg +0 -0
- {parsehub-2.3.8 → parsehub-2.3.9}/src/__init__.py +0 -0
- {parsehub-2.3.8 → parsehub-2.3.9}/src/parsehub/__init__.py +0 -0
- {parsehub-2.3.8 → parsehub-2.3.9}/src/parsehub/cli.py +0 -0
- {parsehub-2.3.8 → parsehub-2.3.9}/src/parsehub/cli_config.py +0 -0
- {parsehub-2.3.8 → parsehub-2.3.9}/src/parsehub/config/__init__.py +0 -0
- {parsehub-2.3.8 → parsehub-2.3.9}/src/parsehub/config/config.py +0 -0
- {parsehub-2.3.8 → parsehub-2.3.9}/src/parsehub/errors.py +0 -0
- {parsehub-2.3.8 → parsehub-2.3.9}/src/parsehub/parsers/__init__.py +0 -0
- {parsehub-2.3.8 → parsehub-2.3.9}/src/parsehub/parsers/base/__init__.py +0 -0
- {parsehub-2.3.8 → parsehub-2.3.9}/src/parsehub/parsers/base/base.py +0 -0
- {parsehub-2.3.8 → parsehub-2.3.9}/src/parsehub/parsers/base/ytdlp.py +0 -0
- {parsehub-2.3.8 → parsehub-2.3.9}/src/parsehub/parsers/parser/__init__.py +0 -0
- {parsehub-2.3.8 → parsehub-2.3.9}/src/parsehub/parsers/parser/bangumi.py +0 -0
- {parsehub-2.3.8 → parsehub-2.3.9}/src/parsehub/parsers/parser/bilibili.py +0 -0
- {parsehub-2.3.8 → parsehub-2.3.9}/src/parsehub/parsers/parser/coolapk.py +0 -0
- {parsehub-2.3.8 → parsehub-2.3.9}/src/parsehub/parsers/parser/douban.py +0 -0
- {parsehub-2.3.8 → parsehub-2.3.9}/src/parsehub/parsers/parser/douyin.py +0 -0
- {parsehub-2.3.8 → parsehub-2.3.9}/src/parsehub/parsers/parser/facebook.py +0 -0
- {parsehub-2.3.8 → parsehub-2.3.9}/src/parsehub/parsers/parser/instagram.py +0 -0
- {parsehub-2.3.8 → parsehub-2.3.9}/src/parsehub/parsers/parser/kuaishou.py +0 -0
- {parsehub-2.3.8 → parsehub-2.3.9}/src/parsehub/parsers/parser/medium.py +0 -0
- {parsehub-2.3.8 → parsehub-2.3.9}/src/parsehub/parsers/parser/pipix.py +0 -0
- {parsehub-2.3.8 → parsehub-2.3.9}/src/parsehub/parsers/parser/snapchat.py +0 -0
- {parsehub-2.3.8 → parsehub-2.3.9}/src/parsehub/parsers/parser/threads.py +0 -0
- {parsehub-2.3.8 → parsehub-2.3.9}/src/parsehub/parsers/parser/tieba.py +0 -0
- {parsehub-2.3.8 → parsehub-2.3.9}/src/parsehub/parsers/parser/tiktok.py +0 -0
- {parsehub-2.3.8 → parsehub-2.3.9}/src/parsehub/parsers/parser/toutiao.py +0 -0
- {parsehub-2.3.8 → parsehub-2.3.9}/src/parsehub/parsers/parser/twitter.py +0 -0
- {parsehub-2.3.8 → parsehub-2.3.9}/src/parsehub/parsers/parser/weibo.py +0 -0
- {parsehub-2.3.8 → parsehub-2.3.9}/src/parsehub/parsers/parser/weixin.py +0 -0
- {parsehub-2.3.8 → parsehub-2.3.9}/src/parsehub/parsers/parser/wxchannels.py +0 -0
- {parsehub-2.3.8 → parsehub-2.3.9}/src/parsehub/parsers/parser/xhs.py +0 -0
- {parsehub-2.3.8 → parsehub-2.3.9}/src/parsehub/parsers/parser/youtube.py +0 -0
- {parsehub-2.3.8 → parsehub-2.3.9}/src/parsehub/parsers/parser/zhihu.py +0 -0
- {parsehub-2.3.8 → parsehub-2.3.9}/src/parsehub/parsers/parser/zuiyou.py +0 -0
- {parsehub-2.3.8 → parsehub-2.3.9}/src/parsehub/provider_api/__init__.py +0 -0
- {parsehub-2.3.8 → parsehub-2.3.9}/src/parsehub/provider_api/bangumi.py +0 -0
- {parsehub-2.3.8 → parsehub-2.3.9}/src/parsehub/provider_api/bilibili.py +0 -0
- {parsehub-2.3.8 → parsehub-2.3.9}/src/parsehub/provider_api/coolapk.py +0 -0
- {parsehub-2.3.8 → parsehub-2.3.9}/src/parsehub/provider_api/douban.py +0 -0
- {parsehub-2.3.8 → parsehub-2.3.9}/src/parsehub/provider_api/douyin.py +0 -0
- {parsehub-2.3.8 → parsehub-2.3.9}/src/parsehub/provider_api/instagram.py +0 -0
- {parsehub-2.3.8 → parsehub-2.3.9}/src/parsehub/provider_api/kuaishou.py +0 -0
- {parsehub-2.3.8 → parsehub-2.3.9}/src/parsehub/provider_api/medium.py +0 -0
- {parsehub-2.3.8 → parsehub-2.3.9}/src/parsehub/provider_api/pipix.py +0 -0
- {parsehub-2.3.8 → parsehub-2.3.9}/src/parsehub/provider_api/threads.py +0 -0
- {parsehub-2.3.8 → parsehub-2.3.9}/src/parsehub/provider_api/tieba.py +0 -0
- {parsehub-2.3.8 → parsehub-2.3.9}/src/parsehub/provider_api/tiktok.py +0 -0
- {parsehub-2.3.8 → parsehub-2.3.9}/src/parsehub/provider_api/toutiao.py +0 -0
- {parsehub-2.3.8 → parsehub-2.3.9}/src/parsehub/provider_api/twitter.py +0 -0
- {parsehub-2.3.8 → parsehub-2.3.9}/src/parsehub/provider_api/weibo.py +0 -0
- {parsehub-2.3.8 → parsehub-2.3.9}/src/parsehub/provider_api/weixin.py +0 -0
- {parsehub-2.3.8 → parsehub-2.3.9}/src/parsehub/provider_api/wxchannels.py +0 -0
- {parsehub-2.3.8 → parsehub-2.3.9}/src/parsehub/provider_api/xhs.py +0 -0
- {parsehub-2.3.8 → parsehub-2.3.9}/src/parsehub/provider_api/zhihu.py +0 -0
- {parsehub-2.3.8 → parsehub-2.3.9}/src/parsehub/provider_api/zuiyou.py +0 -0
- {parsehub-2.3.8 → parsehub-2.3.9}/src/parsehub/types/__init__.py +0 -0
- {parsehub-2.3.8 → parsehub-2.3.9}/src/parsehub/types/callback.py +0 -0
- {parsehub-2.3.8 → parsehub-2.3.9}/src/parsehub/types/media_file.py +0 -0
- {parsehub-2.3.8 → parsehub-2.3.9}/src/parsehub/types/media_ref.py +0 -0
- {parsehub-2.3.8 → parsehub-2.3.9}/src/parsehub/types/platform.py +0 -0
- {parsehub-2.3.8 → parsehub-2.3.9}/src/parsehub/types/post.py +0 -0
- {parsehub-2.3.8 → parsehub-2.3.9}/src/parsehub/types/result.py +0 -0
- {parsehub-2.3.8 → parsehub-2.3.9}/src/parsehub/utils/downloader.py +0 -0
- {parsehub-2.3.8 → parsehub-2.3.9}/src/parsehub/utils/helpers.py +0 -0
- {parsehub-2.3.8 → parsehub-2.3.9}/src/parsehub/utils/media_info.py +0 -0
- {parsehub-2.3.8 → parsehub-2.3.9}/src/parsehub.egg-info/SOURCES.txt +0 -0
- {parsehub-2.3.8 → parsehub-2.3.9}/src/parsehub.egg-info/dependency_links.txt +0 -0
- {parsehub-2.3.8 → parsehub-2.3.9}/src/parsehub.egg-info/entry_points.txt +0 -0
- {parsehub-2.3.8 → parsehub-2.3.9}/src/parsehub.egg-info/requires.txt +0 -0
- {parsehub-2.3.8 → parsehub-2.3.9}/src/parsehub.egg-info/top_level.txt +0 -0
- {parsehub-2.3.8 → parsehub-2.3.9}/test/test_cli.py +0 -0
- {parsehub-2.3.8 → parsehub-2.3.9}/test/test_cli_config.py +0 -0
- {parsehub-2.3.8 → parsehub-2.3.9}/test/test_core_offline.py +0 -0
- {parsehub-2.3.8 → parsehub-2.3.9}/test/test_downloader.py +0 -0
|
@@ -54,7 +54,23 @@ class XiaoHeiHeParser(BaseParser):
|
|
|
54
54
|
images: list[ImageRef | AniRef] = []
|
|
55
55
|
for media in xhh.media or []:
|
|
56
56
|
if media.type == XiaoHeiHeMediaType.IMAGE:
|
|
57
|
-
images.append(
|
|
57
|
+
images.append(
|
|
58
|
+
ImageRef(
|
|
59
|
+
url=media.url,
|
|
60
|
+
thumb_url=media.thumb_url,
|
|
61
|
+
ext=media.ext or "jpg",
|
|
62
|
+
width=media.width or 0,
|
|
63
|
+
height=media.height or 0,
|
|
64
|
+
)
|
|
65
|
+
)
|
|
58
66
|
else:
|
|
59
|
-
images.append(
|
|
67
|
+
images.append(
|
|
68
|
+
AniRef(
|
|
69
|
+
url=media.url,
|
|
70
|
+
thumb_url=media.thumb_url,
|
|
71
|
+
ext=media.ext or "gif",
|
|
72
|
+
width=media.width or 0,
|
|
73
|
+
height=media.height or 0,
|
|
74
|
+
)
|
|
75
|
+
)
|
|
60
76
|
return images
|
|
@@ -23,6 +23,11 @@ from cryptography.hazmat.primitives.ciphers.modes import CBC, ECB
|
|
|
23
23
|
from markdownify import MarkdownConverter
|
|
24
24
|
|
|
25
25
|
|
|
26
|
+
def original_image_url(url: str) -> str:
|
|
27
|
+
path = url.split("?", 1)[0]
|
|
28
|
+
return re.sub(r"/thumb\.(\w+)$", r".\1", path)
|
|
29
|
+
|
|
30
|
+
|
|
26
31
|
class XiaoHeiHePostType(Enum):
|
|
27
32
|
VIDEO = "video"
|
|
28
33
|
IMAGE = "image" # 图文, 单张或多张图片 + 文案
|
|
@@ -40,6 +45,7 @@ class XiaoHeiHeMedia:
|
|
|
40
45
|
type: XiaoHeiHeMediaType
|
|
41
46
|
url: str
|
|
42
47
|
thumb_url: str | None = None
|
|
48
|
+
ext: str | None = None
|
|
43
49
|
height: int | None = None
|
|
44
50
|
width: int | None = None
|
|
45
51
|
|
|
@@ -89,11 +95,14 @@ class XiaoHeiHeAPI:
|
|
|
89
95
|
for image in text_list[1:]:
|
|
90
96
|
if image["type"] == "img":
|
|
91
97
|
media_type = XiaoHeiHeMediaType.GIF if ".gif" in image["url"] else XiaoHeiHeMediaType.IMAGE
|
|
98
|
+
url = original_image_url(image["url"])
|
|
99
|
+
ext_match = re.search(r"\.([^./]+)$", url)
|
|
92
100
|
images.append(
|
|
93
101
|
XiaoHeiHeMedia(
|
|
94
102
|
type=media_type,
|
|
95
|
-
url=
|
|
103
|
+
url=url,
|
|
96
104
|
thumb_url=image["url"],
|
|
105
|
+
ext=ext_match.group(1) if ext_match else None,
|
|
97
106
|
height=int(float(image.get("height", 0))),
|
|
98
107
|
width=int(float(image.get("width", 0))),
|
|
99
108
|
)
|
|
@@ -134,7 +143,7 @@ class XiaoHeiHeAPI:
|
|
|
134
143
|
"owner_only": "1",
|
|
135
144
|
**sig_params,
|
|
136
145
|
}
|
|
137
|
-
cookies = {"x_xhh_tokenid": await SecuritySm.get_d_id()}
|
|
146
|
+
cookies = {"x_xhh_tokenid": await SecuritySm.get_d_id(self.proxy)}
|
|
138
147
|
async with httpx.AsyncClient(proxy=self.proxy) as cli:
|
|
139
148
|
result = await cli.get(self.api_url + "/bbs/app/link/tree", params=params, cookies=cookies)
|
|
140
149
|
result.raise_for_status()
|
|
@@ -355,6 +364,8 @@ class XHHConverter(MarkdownConverter):
|
|
|
355
364
|
def convert_img(self, el, _, parent_tags):
|
|
356
365
|
alt = el.attrs.get("alt", None) or ""
|
|
357
366
|
src = el.attrs.get("data-original", None) or ""
|
|
367
|
+
if src:
|
|
368
|
+
src = original_image_url(src)
|
|
358
369
|
title = el.attrs.get("title", None) or ""
|
|
359
370
|
title_part = ' "{}"'.format(title.replace('"', r"\"")) if title else ""
|
|
360
371
|
options = cast(dict[str, Any], getattr(self, "options")) # noqa: B009
|
|
@@ -504,7 +515,7 @@ class SecuritySm:
|
|
|
504
515
|
return v + smsk_web + "0"
|
|
505
516
|
|
|
506
517
|
@classmethod
|
|
507
|
-
async def get_d_id(cls):
|
|
518
|
+
async def get_d_id(cls, proxy: str | None = None):
|
|
508
519
|
uid = str(uuid.uuid4()).encode("utf-8")
|
|
509
520
|
priId = hashlib.md5(uid).hexdigest()[0:16]
|
|
510
521
|
encrypted_uid = cls.PK.encrypt(uid, padding.PKCS1v15())
|
|
@@ -531,7 +542,7 @@ class SecuritySm:
|
|
|
531
542
|
des_target["tn"] = hashlib.md5(cls.get_tn(des_target).encode()).hexdigest()
|
|
532
543
|
|
|
533
544
|
des_result = cls._AES(cls.GZIP(cls._DES(des_target)), priId.encode("utf-8"))
|
|
534
|
-
async with httpx.AsyncClient() as client:
|
|
545
|
+
async with httpx.AsyncClient(proxy=proxy) as client:
|
|
535
546
|
response = await client.post(
|
|
536
547
|
cls.DEVICES_INFO_URL,
|
|
537
548
|
json={
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|