You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Django后端添加可运行Python脚本的API端点

实现方案

直接按下面的步骤开发即可,不需要依赖django-extensions的runscript功能,就是常规的Django API开发逻辑:

1. 整理现有脚本与公共配置

先在需要新增接口的Django app下新建services目录,把你写的爬取函数存为reddit_tracker.py放入该目录。
PRAW的连接实例不要每次接口请求都新建,把凭证配置统一放到settings.py,生产环境从环境变量读取,禁止硬编码提交到代码仓库:

# settings.py 追加配置
import os
PRAW_CLIENT_ID = os.getenv("PRAW_CLIENT_ID")
PRAW_CLIENT_SECRET = os.getenv("PRAW_CLIENT_SECRET")
PRAW_USER_AGENT = os.getenv("PRAW_USER_AGENT", "django-reddit-tracker/1.0")

2. 编写接口视图

前后端分离场景推荐直接用DRF(Django REST Framework)写接口,核心逻辑就是:接收前端传入的自定义参数,调用你已写好的爬取函数,把结果格式化后返回。
在app的views.py中添加如下代码:

from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
import praw
from django.conf import settings
from .services.reddit_tracker import track_mentions_in_past_24_hours

# 全局初始化一次PRAW实例,复用连接减少重复建连开销
reddit = praw.Reddit(
    client_id=settings.PRAW_CLIENT_ID,
    client_secret=settings.PRAW_CLIENT_SECRET,
    user_agent=settings.PRAW_USER_AGENT
)

# 替换为你自己的初始活跃股票字典
BASE_ACTIVE_STOCKS = {}

class RedditMentionAPIView(APIView):
    def get(self, request):
        # 从请求参数读取前端传值,未传则使用默认值
        subname = request.query_params.get("subname", "wallstreetbets")
        time_filter = request.query_params.get("time_filter", "day")
        limit = request.query_params.get("limit", None)

        # 基础参数校验
        if limit is not None:
            try:
                limit = int(limit)
            except ValueError:
                return Response({"error": "limit参数必须传入整数"}, status=status.HTTP_400_BAD_REQUEST)
        if time_filter not in ["hour", "day", "week", "month", "year", "all"]:
            return Response({"error": "time_filter参数不合法"}, status=status.HTTP_400_BAD_REQUEST)

        try:
            # *注意:copy一份基础字典传入,避免爬取过程修改全局变量,导致不同请求之间数据污染*
            mention_result = track_mentions_in_past_24_hours(
                reddit=reddit,
                subname=subname,
                active_stocks=BASE_ACTIVE_STOCKS.copy(),
                time_filter=time_filter,
                limit=limit
            )
            # 转换为你需要的(条目, 提及次数)元组列表格式
            format_result = list(mention_result.items())
            return Response({
                "code": 0,
                "data": format_result,
                "params": {
                    "subname": subname,
                    "time_filter": time_filter,
                    "limit": limit
                }
            })
        except Exception as e:
            return Response({"error": f"数据获取失败: {str(e)}"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

如果项目没有安装DRF,用Django原生JsonResponse编写逻辑完全一致,参数从request.GET中读取即可。

3. 绑定路由

在app的urls.py中给新增的视图绑定路由地址:

from django.urls import path
from .views import RedditMentionAPIView

urlpatterns = [
    # 保留你原有的其他路由
    path("api/reddit/mentions/", RedditMentionAPIView.as_view(), name="reddit-mention-api"),
]

如果当前app的路由没有被项目根urls.py引入,记得在根路由文件中用include把app的路由规则添加进去。

4. Heroku部署适配

  • 把praw、djangorestframework(如果用了DRF)加到项目根目录的requirements.txt中,Heroku构建时会自动安装对应依赖。
  • 进入Heroku后台的项目Config Vars配置页,把PRAW_CLIENT_ID、PRAW_CLIENT_SECRET两个凭证值填入环境变量,不要硬编码在代码中。
  • 注意:Heroku普通web请求的默认超时时间是30秒,如果你的爬取逻辑耗时可能超过30秒,建议给接口加缓存:相同参数的请求结果缓存5-10分钟,不用每次都实时爬,既能提速也能避免触发Reddit的接口频率限制。如果确实需要长时间爬取,就把逻辑改成Celery异步任务,前端先提交任务,再轮询拿结果即可。

5. 前端调用方式

前端直接发GET请求到接口地址,自定义参数拼在URL query中即可,比如要爬取r/stocks板块过去一周的提及数据,请求地址就是https://你的heroku应用域名/api/reddit/mentions/?subname=stocks&time_filter=week,返回的data字段就是需要的(条目, 提及次数)元组列表。


内容的提问来源于stack exchange,提问作者chiralcentre

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 00:12:25