Skip to content

Commit

Permalink
fix: 修复了douyin关注用户排序类型翻页的问题 (#210)
Browse files Browse the repository at this point in the history
  • Loading branch information
Johnserf-Seed committed Dec 10, 2024
1 parent 6017d37 commit 96af400
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 19 deletions.
34 changes: 27 additions & 7 deletions docs/guide/apps/douyin/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -469,23 +469,43 @@ outline: deep
| user_id| str | 用户ID |
| sec_user_id| str | 用户ID |
| offset| int | 页码,初始为0 |
| count| int | 页数,初始为20 |
| min_time | int | 最早关注时间戳,秒级,初始为0 |
| max_time | int | 最晚关注时间戳,秒级,初始为0 |
| count| int | 每页关注用户数,初始为20 |
| source_type| int | 排序类型,初始为4 |
| min_time | int | 最早关注时间戳,初始为0 |
| max_time | int | 最晚关注时间戳,初始为0 |
| max_counts| float | 最大列表数,初始为None |

| 返回 | 类型 | 说明 |
| :--- | :--- | :--- |
| UserFollowingFilter | AsyncGenerator | 关注用户数据过滤器,包含关注用户数据的_to_raw、_to_dict、_to_list方法 |

<<< @/snippets/douyin/user-following.py{18-20,22-29}
#### 偏移量 (**offset**):

::: tip 提示
- `source_type` 的参数控制排序类型,`4` 为综合排序,`1` 为最近关注 `3` 为最早关注。
- 当选择 `source_type` 不为 `4` 时,需要`min_time``max_time` 参数选择时间范围。
-`source_type``1``3` 时,`offset` 参数无效。
-`source_type``4` 时,`offset` 参数有效。

#### 时间范围 (**min_time**/**max_time**):

- 如果未传递 `max_time``min_time` 参数,`F2` 将自动处理时间范围,确保数据完整性。
- 若需要自定义时间范围,可通过手动设置 `max_time``min_time` 参数实现。

#### 关注用户数 (**count**):

- `count` 参数控制每页关注用户数,不建议设置过大,建议使用默认值。

#### 排序类型 (**source_type**):

- `1` 表示按最近关注排序。
- `3` 表示按最早关注排序。
- `4` 表示按综合排序。

::: tip :bulb: 但需注意
- 只能获取到用户**公开状态**的关注用户数据。
- 时间间隔过长可能导致数据不完整,不建议采用自定义时间范围,仅适用于获取特定时间段前或后的数据场景。
:::

<<< @/snippets/douyin/user-following.py{18-20,22-31}

### 粉丝用户数据 🟢

异步方法,用于获取指定用户的粉丝列表。
Expand Down
2 changes: 2 additions & 0 deletions docs/snippets/douyin/user-following.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,14 @@ async def main():
# sec_user_id = "MS4wLjABAAAAGPm-wPeGQuziCu5z6KerQA7WmSTnS99c8lU8WLToB0BsN02mqbPxPuxwDjKf7udZ" # 隐私设置的账号

# 至少提供 user_id 或 sec_user_id 中的一个参数
# source_type 选择排序方式,1:按照最近关注排序,3:按照最早关注排序,4:按照综合排序
# 根据 max_time 和 min_time 区间获取关注用户列表
async for following in DouyinHandler(kwargs).fetch_user_following(
user_id=user_id,
sec_user_id=sec_user_id,
# max_time=1668606509,
# min_time=0,
source_type=4,
):
if following.status_code != 0:
logger.error(
Expand Down
39 changes: 27 additions & 12 deletions f2/apps/douyin/handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -1498,51 +1498,59 @@ async def fetch_user_following(
user_id: str = "",
sec_user_id: str = "",
offset: int = 0,
count: int = 20,
source_type: int = 4,
min_time: int = 0,
max_time: int = 0,
count: int = 20,
source_type: int = 4,
max_counts: float = float("inf"),
) -> AsyncGenerator[UserFollowingFilter, Any]:
"""
用于获取指定用户关注的用户的作品列表。
Args:
user_id: str: 用户ID
sec_user_id: str: 用户ID
sec_user_id: str: 用户sec_user_id
offset: int: 起始页
min_time: int: 最小时间戳,秒级,初始为0
max_time: int: 最大时间戳,秒级,初始为0
count: int: 每页关注用户数
source_type: int: 排序类型
min_time: int: 最小时间戳
max_time: int: 最大时间戳
source_type: int: 排序类型,1: 按最近关注排序,3: 按最早关注排序,4: 按综合排序
Return:
following: AsyncGenerator[UserFollowingFilter, Any]: 关注用户数据过滤器,包含关注用户数据的_to_raw、_to_dict、_to_list方法
"""

if not user_id and not sec_user_id:
raise ValueError(_("至少提供 user_id 或 sec_user_id 中的一个参数"))

source_type_map = {
1: _("按最近关注排序"),
3: _("按最早关注排序"),
4: _("按综合排序"),
}
max_counts = max_counts or float("inf")
users_collected = 0

logger.info(_("处理用户:{0} 的关注用户").format(sec_user_id))
logger.info(_("当前排序类型:{0}").format(source_type_map.get(source_type)))

while users_collected < max_counts:
current_request_size = min(count, max_counts - users_collected)

logger.debug(
_("最大数量:{0} 每次请求数量:{1}").format(count, current_request_size)
)
logger.debug(_("当前请求的 max_time:{0}".format(max_time)))
logger.debug(_("当前请求的 min_time:{0}".format(min_time)))

async with DouyinCrawler(self.kwargs) as crawler:
params = UserFollowing(
offset=offset,
count=current_request_size,
user_id=user_id,
sec_user_id=sec_user_id,
source_type=source_type,
offset=offset,
min_time=min_time,
max_time=max_time,
count=current_request_size,
source_type=source_type,
)
response = await crawler.fetch_user_following(params)
following = UserFollowingFilter(response)
Expand All @@ -1552,8 +1560,8 @@ async def fetch_user_following(
logger.info(_("用户:{0} 所有关注用户采集完毕").format(sec_user_id))
break

logger.info(_("当前请求的offset:{0}").format(offset))
logger.info(_("处理了 {0} 个关注用户").format(offset + 1))
logger.info(_("当前请求的 offset:{0}").format(offset))
logger.info(_("处理了 {0} 个关注用户").format(len(following.sec_uid)))
logger.debug(
_("用户ID:{0} 用户昵称:{1} 用户作品数:{2} 额外内容:{3}").format(
following.sec_uid,
Expand All @@ -1565,7 +1573,14 @@ async def fetch_user_following(

# 更新已经处理的用户数量 (Update the number of users processed)
users_collected += len(following.sec_uid)
offset = following.offset

# 使用逻辑映射表更新offset、max_time、min_time
logicmap = {
1: (0, following.min_time, 0), # 按最近关注排序
3: (0, 0, following.max_time), # 按最早关注排序
4: (following.offset, 0, 0), # 按综合排序
}
offset, max_time, min_time = logicmap.get(source_type)

# 避免请求过于频繁
logger.info(_("等待 {0} 秒后继续").format(self.kwargs.get("timeout", 5)))
Expand Down

0 comments on commit 96af400

Please sign in to comment.