前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【Python实战】基于Python实现博客评论区抽奖功能

【Python实战】基于Python实现博客评论区抽奖功能

原创
作者头像
王二蛋
修改2024-02-08 13:44:01
32146
代码可运行
修改2024-02-08 13:44:01
运行总次数:6
代码可运行

前言

最近不少博主反馈,想为粉丝谋点福利,但是不知道以什么方式抽选幸运粉丝,我给他们支了个招:“可以在你的文章评论区抽选”。

但是每次都要人工介入,第一是耗时,第二是可能会带有主观意识,做不到完全公平。

这时,我又给他们支了个招:“写个程序随机抽选呗”。

所以,我这个“大聪明”就用Python编写了一个评论区抽选粉丝程序。为了秉行公平、公正、公开原则,本文会将抽选粉丝程序的思路以及代码的实现展示给大家,有需要的拿走不谢。

还有,腾讯开发者社区推出了新功能【在线运行代码块】,所以,大家在阅读文章的过程中就可以在浏览器上直接运行代码看效果了。如下图

抽选规则

抽选评论区中的粉丝要符合以下条件:

  1. 关注了我,即成为我的粉丝。
  2. 评论一次,权重+1,最多3次。

实现思路

  1. 首先需要获取该博客文章的所有评论者。
  2. 筛选符合条件的评论者。
    • 是否为我的粉丝。
    • 评论是否符合当期要求内容(可选)。
  3. 在符合条件的粉丝中随机抽选幸运读者。

代码实现

1.获取评论数据

虽然腾讯云开发者社区不提供直接获取文章评论者的接口,但这难不倒一个开发人员。

我们可以在文章所在页面开启调试模式拿到这个接口:

/developer/api/comment/nest-list,参数也清晰明了,如下:

代码语言:yaml
复制
{
    "page":1, 
    "objectId":2377595, #文章编号,/developer/article/2377595
    "module":5,
    "sortField":"timeline",
    "pagesize":10
}

响应格式如下:

代码语言:yaml
复制
{
    "list":[
        {
            "beCommentUid":0,
            "channel":"",
            "commentId":...,
            "commentUid":...,
            "content":"...",
            "createTime":...,
            "from":{
                "avatarUrl":"...",
                "nickname":"...",
                "uid":...
            },
            "isLike":0,
            "likeNum":0,
            "module":5,
            "objectId":...,
            "pCommentId":0,
            "rCommentId":0,
            "status":2,
            "subComments":[

            ],
            "subObjectId":0,
            "weight":0
        },
        ....
    ],
    "total":2,
    "validTotal":2
}

接下来就可以基于Python中的requests包直接发起POST请求获取评论数据了,代码如下:

代码语言:python
代码运行次数:2
复制
import requests

if __name__ == '__main__':
    # 评论数据接口
    commentUrl = "/developer/api/comment/nest-list"
    # 每次获取评论的数量
    pageSize = 10
    # 文章编号
    objectId=2377595
    # 评论数据接口
    data = {"page": 1, "objectId": objectId, "module": 5, "sortField": "timeline", "pagesize": pageSize}
    headers = {"Content-Type": "application/json", "User-Agent": ""}
    response = requests.post(commentUrl, json=data, headers=headers)
    # 如果请求成功,接收的响应会是一个Response对象
    if response.status_code == 200:
        # 使用json()方法将响应内容解析为JSON
        data = response.json()
        print(data)
    else:
        print("请求失败,状态码:", response.status_code)

这里输出的data就是评论数据。当然,为了实现该接口的分页功能以及代码的可读性和可重用性,这里做一下简单的封装。

代码语言:python
代码运行次数:3
复制
import requests


# 调用接口获取数据
def request(url, data):
    headers = {"Content-Type": "application/json", "User-Agent": ""}
    response = requests.post(url, json=data, headers=headers)
    # 如果请求成功,接收的响应会是一个Response对象
    if response.status_code == 200:
        # 使用json()方法将响应内容解析为JSON
        return response.json()
    else:
        print("请求失败,状态码:", response.status_code)


# 获取到所有的评论
def get_comments():
    data = {"page": 1, "objectId": objectId, "module": 5, "sortField": "timeline", "pagesize": pageSize}
    res = request(commentUrl, data)
    # 解析到总页数
    total_pages = res["total"] // pageSize
    # 解析到评论数据
    commentList = res["list"]
    assert len(commentList) > 0, "该博客没有评论数据"
    # 合并所有的评论
    commentList = commentList + [_data["list"] for _data in [request(commentUrl,
                                                                     {"page": page, "objectId": objectId, "module": 5,
                                                                      "sortField": "timeline", "pagesize": pageSize})
                                                             for page in range(2, total_pages + 2)]]
    return commentList

if __name__ == '__main__':
    # 评论数据接口
    commentUrl = "/developer/api/comment/nest-list"
    # 每次获取评论的数量
    pageSize = 10
    # 文章编号
    objectId = 2383111
    print(get_comments())

如代码所示,将请求接口抽出来作为独立接口,这样,其他url的请求就可以共用了。

2.过滤符合抽选规则的评论者

在获取到评论数据后,我们需要过滤掉不符合规则的评论者。例如,本片文章要求评论为“Java一枝花”,但是读者评论了“666”就不符合参与规则了。

现在需要评论内容和评论者这两个数据就可以完成该需求了,即评论接口响应中的contentfrom中的nickname

接下来就可以根据条件筛选评论者,评论一次权重+1。代码如下,主要关注get_comment_users()这个方法。

代码语言:python
代码运行次数:0
复制
import requests


# 调用接口获取数据
def request(url, data):
    headers = {"Content-Type": "application/json", "User-Agent": ""}
    response = requests.post(url, json=data, headers=headers)
    # 如果请求成功,接收的响应会是一个Response对象
    if response.status_code == 200:
        # 使用json()方法将响应内容解析为JSON
        return response.json()
    else:
        print("请求失败,状态码:", response.status_code)


# 获取到所有的评论
def get_comments():
    data = {"page": 1, "objectId": objectId, "module": 5, "sortField": "timeline", "pagesize": pageSize}
    res = request(commentUrl, data)
    # 解析到总页数
    total_pages = res["total"] // pageSize
    # 解析到评论数据
    commentList = res["list"]
    assert len(commentList) > 0, "该博客没有评论数据"
    # 合并所有的评论
    commentList = commentList + [_data["list"] for _data in [request(commentUrl,
                                                                     {"page": page, "objectId": objectId, "module": 5,
                                                                      "sortField": "timeline", "pagesize": pageSize})
                                                             for page in range(2, total_pages + 2)]]
    return commentList

# 获取符合条件的评论者
def get_comment_users():
    commentUsers = {}
    for item in get_comments():
        # 解析评论者
        nickName = item["from"]["nickname"]
        # 解析评论内容
        content = item["content"]
        # 判断评论内容是否符合要求
        if len(needcomment) == 0 or needcomment in content:
            commentCount = commentUsers.get(nickName)
            # 组装评论者及其权重
            if commentCount is None:
                commentUsers[nickName] = 1
            else:
                # 最多3条评论
                if commentUsers[nickName] < 3:
                    commentUsers[nickName] = commentCount + 1
    print("符合条件的评论者{}".format(commentUsers))
    return commentUsers

if __name__ == '__main__':
    # 评论数据接口
    commentUrl = "/developer/api/comment/nest-list"
    # 每次获取评论的数量
    pageSize = 10
    # 文章编号
    objectId = 2383111
    # 指定的评论内容
    needcomment=""
    get_comment_users()

commentUsers最终会输出符合要求的评论者,key为昵称,value为权重值,格式如:{'xxx': 1, 'xxx1': 3}

3.获取关注我的人

符合条件的评论者筛选出来后要确定这个人是否为我的粉丝,不是的话将其从commentUsers移除。

为什么先过滤符合要求的评论再获取关注我的人?

因为有的博主粉丝过多,如果直接获取关注我的人,那会调用很多次接口,所以直接在已有的条件下再次过滤即可。

同样,还是在页面中拿到“我的粉丝”接口:

/developer/services/ajax/user-center?action=GetUserFollowers&uin=10000xxx&csrfCode=438895646

该接口中的uin为腾讯云账号id。

获取粉丝数据代码如下get_fans()方法。

代码语言:python
代码运行次数:0
复制
import requests


# 调用接口获取数据
def request(url, data):
    headers = {"Content-Type": "application/json", "User-Agent": ""}
    response = requests.post(url, json=data, headers=headers)
    # 如果请求成功,接收的响应会是一个Response对象
    if response.status_code == 200:
        # 使用json()方法将响应内容解析为JSON
        return response.json()
    else:
        print("请求失败,状态码:", response.status_code)


# 获取到所有的粉丝
def get_fans():
    data = {"action": "GetUserFollowers", "payload": {"uid": uid, "pageNumber": 1, "pageSize": 20}}
    res = request(followersUrl, data)
    # 解析到粉丝数据
    fansList = res["data"]["list"]
    fans_names = [fan["name"] for fan in fansList]
    return fans_names


if __name__ == '__main__':
    # 腾讯云账号ID
    uin = 100008382400
    # 开发者社区uid
    uid = 3981768
    # 关注我的人数据接口
    followersUrl = "/developer/services/ajax/user-center?action=GetUserFollowers&uin={}&csrfCode=438895646".format(
        uin)
    print(get_fans())

4.过滤符合抽选规则的粉丝

在获取到粉丝后,将commentUsers中不在粉丝列表的数据移除就好,代码如下get_satisfied_fans()方法:

代码语言:python
代码运行次数:0
复制
import random

import requests


# 调用接口获取数据
def request(url, data):
    headers = {"Content-Type": "application/json", "User-Agent": ""}
    response = requests.post(url, json=data, headers=headers)
    # 如果请求成功,接收的响应会是一个Response对象
    if response.status_code == 200:
        # 使用json()方法将响应内容解析为JSON
        return response.json()
    else:
        print("请求失败,状态码:", response.status_code)


# 获取到所有的评论
def get_comments():
    data = {"page": 1, "objectId": objectId, "module": 5, "sortField": "timeline", "pagesize": pageSize}
    res = request(commentUrl, data)
    # 解析到总页数
    total_pages = res["total"] // pageSize
    # 解析到评论数据
    commentList = res["list"]
    assert len(commentList) > 0, "该博客没有评论数据"
    # 合并所有的评论
    commentList = commentList + [_data["list"] for _data in [request(commentUrl,
                                                                     {"page": page, "objectId": objectId, "module": 5,
                                                                      "sortField": "timeline", "pagesize": pageSize})
                                                             for page in range(2, total_pages + 2)]]
    return commentList


# 获取符合条件的评论者
def get_comment_users():
    commentUsers = {}
    for item in get_comments():
        # 解析评论者
        nickName = item["from"]["nickname"]
        # 解析评论内容
        content = item["content"]
        # 判断评论内容是否符合要求
        if len(needcomment) == 0 or needcomment in content:
            commentCount = commentUsers.get(nickName)
            # 组装评论者及其权重
            if commentCount is None:
                commentUsers[nickName] = 1
            else:
                # 最多3条评论
                if commentUsers[nickName] < 3:
                    commentUsers[nickName] = commentCount + 1
    print("符合条件的评论者{}".format(commentUsers))
    return commentUsers


# 获取到所有的粉丝
def get_fans():
    data = {"action": "GetUserFollowers", "payload": {"uid": uid, "pageNumber": 1, "pageSize": 20}}
    res = request(followersUrl, data)
    # 解析到粉丝数据
    fansList = res["data"]["list"]
    fans_names = [fan["name"] for fan in fansList]
    return fans_names


# 获取符合抽选规则的粉丝
def get_satisfied_fans(commentUsers):
    fansList = get_fans()
    # 在粉丝列表中的评论者
    fansNickname = list(set(fansList) & set(list(commentUsers.keys())))
    # 移除并返回commentUsers的粉丝
    return {nickname: commentUsers.pop(nickname) for nickname in fansNickname}


if __name__ == '__main__':
    # 评论数据接口
    commentUrl = "/developer/api/comment/nest-list"
    # 每次获取评论的数量
    pageSize = 10
    # 文章编号
    objectId = 2383111
    # 指定的评论内容
    needcomment = ""
    # 腾讯云账号ID
    uin = 100008382400
    # 开发者社区uid
    uid = 3981768
    # 关注我的人数据接口
    followersUrl = "/developer/services/ajax/user-center?action=GetUserFollowers&uin={}&csrfCode=438895646".format(
        uin)

    print("符合抽选规则的粉丝{}".format(get_satisfied_fans(get_comment_users())))

6.抽选粉丝

最后,就可以基于fans随机抽选粉丝了,这里用python自带的random.choices随机方法。

完整的代码

至此,基于Python实现博客评论区抽奖功能就完成了。

由于接口中存在分页问题,同时为了提高代码的可读性和可用性,我对剩余的代码进行了完善,以下是完善后的代码:

代码语言:python
代码运行次数:1
复制
import random

import requests


# 调用接口获取数据
def request(url, data):
    headers = {"Content-Type": "application/json", "User-Agent": ""}
    response = requests.post(url, json=data, headers=headers)
    # 如果请求成功,接收的响应会是一个Response对象
    if response.status_code == 200:
        # 使用json()方法将响应内容解析为JSON
        return response.json()
    else:
        print("请求失败,状态码:", response.status_code)


# 获取到所有的评论
def get_comments():
    data = {"page": 1, "objectId": objectId, "module": 5, "sortField": "timeline", "pagesize": pageSize}
    res = request(commentUrl, data)
    # 解析到总页数
    total_pages = res["total"] // pageSize
    # 解析到评论数据
    commentList = res["list"]
    assert len(commentList) > 0, "该博客没有评论数据"
    # 合并所有的评论
    commentList = commentList + [_data["list"] for _data in [request(commentUrl,
                                                                     {"page": page, "objectId": objectId, "module": 5,
                                                                      "sortField": "timeline", "pagesize": pageSize})
                                                             for page in range(2, total_pages + 2)]]
    return commentList


# 获取符合条件的评论者
def get_comment_users():
    commentUsers = {}
    for item in get_comments():
        # 解析评论者
        nickName = item["from"]["nickname"]
        # 解析评论内容
        content = item["content"]
        # 判断评论内容是否符合要求
        if len(needcomment) == 0 or needcomment in content:
            commentCount = commentUsers.get(nickName)
            # 组装评论者及其权重
            if commentCount is None:
                commentUsers[nickName] = 1
            else:
                # 最多3条评论
                if commentUsers[nickName] < 3:
                    commentUsers[nickName] = commentCount + 1
    print("符合条件的评论者{}".format(commentUsers))
    return commentUsers


# 获取到所有的粉丝
def get_fans(page):
    data = {"action": "GetUserFollowers", "payload": {"uid": uid, "pageNumber": page, "pageSize": pageSize}}
    res = request(followersUrl, data)
    # 粉丝数据
    fansList = res["data"]["list"]
    # 粉丝页数
    totalPage = (res["data"]["total"] // pageSize)+1
    fans_names = [fan["name"] for fan in fansList]
    return None if totalPage == page else page+1 , fans_names


# 获取符合抽选规则的粉丝
def get_satisfied_fans(commentUsers, fanId):
    fanId, fansList = get_fans(fanId)
    # 在粉丝列表中的评论者
    fansNickname = list(set(fansList) & set(list(commentUsers.keys())))
    # 移除并返回commentUsers的粉丝
    return fanId, {nickname: commentUsers.pop(nickname) for nickname in fansNickname}


def weighted_random_choice(choices, weights):
    return random.choices(choices, weights=weights)[0]


# 符合抽选规则的粉丝
def satisfied_fans():
    satisfiedFans = {}
    commentUsers = get_comment_users()
    assert commentUsers, "没有符合条件的评论者"
    fanId = 1
    one = True;
    # 如果是第一次或者 fanId 有值 ,并且评论者未被移除完,继续筛选。
    while one or (fanId is not None and commentUsers):
        one = False
        fanId, fans = get_satisfied_fans(commentUsers, fanId)
        satisfiedFans = satisfiedFans | fans

    print("符合抽选规则的粉丝:{}".format(satisfiedFans))
    return satisfiedFans


# 抽选粉丝
def select_fans():
    try:
        fans = satisfied_fans()
        assert fans, "没有符合抽选规则的粉丝"
        print("——————开始抽选粉丝——————")
        for i in range(1, (selectCount if len(fans) >= selectCount else len(fans))+1):
            luckfans = weighted_random_choice(list(fans.keys()), list(fans.values()))
            # 移除该粉丝
            fans.pop(luckfans)
            print("恭喜第{}为幸运粉丝:{}".format(i, luckfans))

    except Exception as e:
        print(e)


if __name__ == '__main__':
    # 评论数据接口
    commentUrl = "/developer/api/comment/nest-list"
    # 每次获取评论的数量
    pageSize = 10
    # 文章编号
    objectId = 2382339
    # 指定的评论内容
    needcomment = ""
    # 腾讯云账号ID
    uin = 100008382400
    # 开发者社区uid
    uid = 3981768
    # 关注我的人数据接口
    followersUrl = "/developer/services/ajax/user-center?action=GetUserFollowers&uin={}&csrfCode=438895646".format(
        uin)
    # 抽选粉丝个数
    selectCount = 3
    select_fans()

效果展示

执行代码中的使用示例后结果如下图,如果粉丝过于多,可能需要等待数秒。

好了,大家快去试试吧。

结语

为了方便大家的使用,我已将程序打包成可执行文件,支持Windows和Mac系统,需要的可以联系博主获取。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 抽选规则
  • 实现思路
  • 代码实现
    • 1.获取评论数据
      • 2.过滤符合抽选规则的评论者
        • 3.获取关注我的人
          • 4.过滤符合抽选规则的粉丝
            • 6.抽选粉丝
            • 完整的代码
            • 效果展示
            • 结语
            相关产品与服务
            云开发 CloudBase
            云开发(Tencent CloudBase,TCB)是腾讯云提供的云原生一体化开发环境和工具平台,为200万+企业和开发者提供高可用、自动弹性扩缩的后端云服务,可用于云端一体化开发多种端应用(小程序、公众号、Web 应用等),避免了应用开发过程中繁琐的服务器搭建及运维,开发者可以专注于业务逻辑的实现,开发门槛更低,效率更高。
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
            http://www.vxiaotou.com