如何用Python(PRAW/PSAW)抓取未上首页的Reddit随机帖子?
解决方案:过滤非首页Reddit帖子并随机排序
首先,咱们先理清你的需求:近3年发布、没上过首页、结果随机分布。你的现有代码已经搞定了时间范围和基础搜索,但还缺过滤和随机化的步骤,下面一步步来优化:
1. 修正时间范围(可选)
你代码里写的是2017年,这已经是6年前的数据了,如果是要近3年的话,得把起始时间改成比如2021年(假设当前是2024年):
start_epoch = int(datetime(2021, 1, 1).timestamp())
2. 过滤"未登上首页"的帖子
Reddit没有直接标记帖子是否上过首页的字段,咱们只能用间接特征来过滤——首页帖子普遍有高点赞、多评论,或者是版主置顶的内容。这里给你两种实用的过滤逻辑:
- 过滤高赞/高评论帖子:首页热门帖子通常点赞数至少几百,你可以设置一个阈值(比如
score < 100,可根据实际情况调整) - 过滤版主置顶帖子:置顶内容更容易被推到首页,用
distinguished=None排除这类帖子
把这些条件加到PSAW的搜索参数里:
gen = api.search_submissions( after=start_epoch, score_lt=100, # 排除点赞数≥100的帖子,间接避开首页热门 distinguished=None, # 排除版主置顶的帖子 limit=500 )
3. 实现随机排序
PSAW默认是按发布时间倒序返回结果,要随机分布的话,先把生成器转成列表,再用random.shuffle打乱:
import random # 把生成器转为列表(注意:如果limit很大,会占用较多内存) submissions = list(gen) # 随机打乱列表 random.shuffle(submissions)
如果你的数据集很大,不想全部加载到内存,可以用蓄水池抽样来在获取数据的同时随机选样本,节省内存:
def reservoir_sample(generator, sample_size): sample = [] for idx, item in enumerate(generator): if idx < sample_size: sample.append(item) else: # 随机替换样本中的元素 replace_idx = random.randint(0, idx) if replace_idx < sample_size: sample[replace_idx] = item return sample # 直接获取500个随机样本,无需加载全部数据 random_submissions = reservoir_sample(gen, 500)
这是最优方案吗?其他建议?
关于当前方案的优缺点:
- ✅ 优点:PSAW基于Pushshift API,请求限制比官方Reddit API(PRAW)宽松,能获取大量历史数据,实现成本低
- ❌ 缺点:过滤逻辑是间接的,可能存在误判(比如少数低赞帖子上过首页,或者高赞帖子没上首页);Pushshift的数据可能存在缺失或延迟
其他优化建议:
- 结合PRAW补充数据:如果需要更精准的判断,可以先用PSAW批量获取帖子ID,再用PRAW(官方API)查询帖子的详细元数据——不过官方API有请求频率限制(每分钟60次),适合小批量数据
- 调整过滤阈值:先手动观察当前首页帖子的平均点赞数/评论数,再调整
score_lt的数值,让过滤更精准 - 分批获取数据:如果需要超过500条的样本,可以去掉
limit参数,循环分页获取,再用蓄水池抽样来随机选取 - 处理数据缺失:Pushshift可能会漏掉部分帖子,你可以在代码里加入异常处理,跳过无法获取的条目
内容的提问来源于stack exchange,提问作者Luke Prior
相关产品推荐
相关产品推荐

