前言
最近不少博主反馈,想为粉丝谋点福利,但是不知道以什么方式抽选幸运粉丝,我给他们支了个招:“可以在你的文章评论区抽选”。
但是每次都要人工介入,第一是耗时,第二是可能会带有主观意识,做不到完全公平。
这时,我又给他们支了个招:“写个程序随机抽选呗”。
所以,我这个“大聪明”就用Python编写了一个评论区抽选粉丝程序。为了秉行公平、公正、公开原则,本文会将抽选粉丝程序的思路以及代码的实现展示给大家,有需要的拿走不谢。
还有,腾讯开发者社区推出了新功能【在线运行代码块】,所以,大家在阅读文章的过程中就可以在浏览器上直接运行代码看效果了。如下图
抽选规则
抽选评论区中的粉丝要符合以下条件:
- 关注了我,即成为我的粉丝。
- 评论一次,权重 1,最多3次。
实现思路
- 首先需要获取该博客文章的所有评论者。
- 筛选符合条件的评论者。
- 是否为我的粉丝。
- 评论是否符合当期要求内容(可选)。
- 在符合条件的粉丝中随机抽选幸运读者。
代码实现
1.获取评论数据
虽然腾讯云开发者社区不提供直接获取文章评论者的接口,但这难不倒一个开发人员。
我们可以在文章所在页面开启调试模式拿到这个接口:
https://cloud.tencent.com/developer/api/comment/nest-list
,参数也清晰明了,如下:
{
"page":1,
"objectId":2377595, #文章编号,https://cloud.tencent.com/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请求获取评论数据了,代码如下:
import requests
if __name__ == '__main__':
# 评论数据接口
commentUrl = "https://cloud.tencent.com/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
就是评论数据。当然,为了实现该接口的分页功能以及代码的可读性和可重用性,这里做一下简单的封装。
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 = "https://cloud.tencent.com/developer/api/comment/nest-list"
# 每次获取评论的数量
pageSize = 10
# 文章编号
objectId = 2383111
print(get_comments())
如代码所示,将请求接口抽出来作为独立接口,这样,其他url
的请求就可以共用了。
2.过滤符合抽选规则的评论者
在获取到评论数据后,我们需要过滤掉不符合规则的评论者。例如,本片文章要求评论为“Java一枝花”,但是读者评论了“666”就不符合参与规则了。
现在需要评论内容和评论者这两个数据就可以完成该需求了,即评论接口响应中的content
和from
中的nickname
。
接下来就可以根据条件筛选评论者,评论一次权重 1。代码如下,主要关注get_comment_users()
这个方法。
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 = "https://cloud.tencent.com/developer/api/comment/nest-list"
# 每次获取评论的数量
pageSize = 10
# 文章编号
objectId = 2383111
# 指定的评论内容
needcomment=""
get_comment_users()
commentUsers
最终会输出符合要求的评论者,key
为昵称,value
为权重值,格式如:{'xxx': 1, 'xxx1': 3}
。
3.获取关注我的人
符合条件的评论者筛选出来后要确定这个人是否为我的粉丝,不是的话将其从commentUsers
移除。
为什么先过滤符合要求的评论再获取关注我的人?
因为有的博主粉丝过多,如果直接获取关注我的人,那会调用很多次接口,所以直接在已有的条件下再次过滤即可。
同样,还是在页面中拿到“我的粉丝”接口:
https://cloud.tencent.com/developer/services/ajax/user-center?action=GetUserFollowers&uin=10000xxx&csrfCode=438895646
该接口中的uin为腾讯云账号id。
获取粉丝数据代码如下get_fans()
方法。
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 = "https://cloud.tencent.com/developer/services/ajax/user-center?action=GetUserFollowers&uin={}&csrfCode=438895646".format(
uin)
print(get_fans())
4.过滤符合抽选规则的粉丝
在获取到粉丝后,将commentUsers中不在粉丝列表的数据移除就好,代码如下get_satisfied_fans()
方法:
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 = "https://cloud.tencent.com/developer/api/comment/nest-list"
# 每次获取评论的数量
pageSize = 10
# 文章编号
objectId = 2383111
# 指定的评论内容
needcomment = ""
# 腾讯云账号ID
uin = 100008382400
# 开发者社区uid
uid = 3981768
# 关注我的人数据接口
followersUrl = "https://cloud.tencent.com/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 = "https://cloud.tencent.com/developer/api/comment/nest-list"
# 每次获取评论的数量
pageSize = 10
# 文章编号
objectId = 2382339
# 指定的评论内容
needcomment = ""
# 腾讯云账号ID
uin = 100008382400
# 开发者社区uid
uid = 3981768
# 关注我的人数据接口
followersUrl = "https://cloud.tencent.com/developer/services/ajax/user-center?action=GetUserFollowers&uin={}&csrfCode=438895646".format(
uin)
# 抽选粉丝个数
selectCount = 3
select_fans()
效果展示
执行代码中的使用示例后结果如下图,如果粉丝过于多,可能需要等待数秒。
好了,大家快去试试吧。
结语
为了方便大家的使用,我已将程序打包成可执行文件,支持Windows和Mac系统,需要的可以联系博主获取。