用Python进行reddit监视
#python #reddit #socialmedia #sociallistening

最初发表在https://segue.co/blog/reddit-monitoring-python

所有源代码都可以在此处找到:
https://github.com/theleonwei/reddit_bot

简介:
Reddit是美国第二大受欢迎的网站,每月有超过3亿个唯一的访客。

它也是互联网上运输最多的网站之一,已成为各行业品牌的在线营销策略的重要组成部分。

本文将向您展示如何使用Python和Praw库在Reddit上编程设置关键字监视器服务。

您还将学习如何使用Django设置此Web服务,并在本地计算机上运行它以监视Reddit,将潜在客户自动保存到数据库中。

所有代码和分步说明都是基于您在a上的假设。

目录:

  • 使用CookieCutter模板设置Django项目
  • 注册REDDIT应用程序并安装Praw Library
  • 带正则表达式的关键字监视
  • 将数据持续到Postgres数据库
  • 领导报告视图
  • 安排一份cron工作以定期检查reddit

使用CookieCutter模板设置Django项目
CookieCutter Django是快速开始生产Django项目的框架。

要了解更多信息,您可以在GitHub上访问他们的官方网站:

https://github.com/cookiecutter/cookiecutter-django

步骤1:安装CookieCutter。
打开您最喜欢的终端应用程序(我的是Iterm2),然后安装最新的CookieCutter。

pip install "cookiecutter>=1.7.0"

步骤2:启动Django项目。

cookiecutter https://github.com/cookiecutter/cookiecutter-django

遵循指令,回答问题并设置项目;这是我的选择:

project_name [My Awesome Project]: Reddit Bot
project_slug [reddit_bot]:
description [Behold My Awesome Project!]: My awesome Reddit Bot Project
author_name [Daniel Roy Greenfeld]: Leon W
domain_name [example.com]:
email [leon-w@example.com]:
version [0.1.0]:
Select open_source_license:
1 - MIT
2 - BSD
3 - GPLv3
4 - Apache Software License 2.0
5 - Not open source
Choose from 1, 2, 3, 4, 5 [1]: 5
timezone [UTC]: US/Pacific
windows [n]:
use_pycharm [n]: y
use_docker [n]:
Select postgresql_version:
1 - 14
2 - 13
3 - 12
4 - 11
5 - 10
Choose from 1, 2, 3, 4, 5 [1]:
Select cloud_provider:
1 - AWS
2 - GCP
3 - None
Choose from 1, 2, 3 [1]:
Select mail_service:
1 - Mailgun
2 - Amazon SES
3 - Mailjet
4 - Mandrill
5 - Postmark
6 - Sendgrid
7 - SendinBlue
8 - SparkPost
9 - Other SMTP
Choose from 1, 2, 3, 4, 5, 6, 7, 8, 9 [1]:
use_async [n]: n
use_drf [n]: n
Select frontend_pipeline:
1 - None
2 - Django Compressor
3 - Gulp
Choose from 1, 2, 3 [1]:
use_celery [n]: n
use_mailhog [n]: n
use_sentry [n]: n
use_whitenoise [n]: n
use_heroku [n]: y
Select ci_tool:
1 - None
2 - Travis
3 - Gitlab
4 - Github
Choose from 1, 2, 3, 4 [1]:
keep_local_envs_in_vcs [y]: n
debug [n]: n
 [SUCCESS]: Project initialized, keep up the good work!

步骤3:安装依赖项

cd reddit_bot; ls

这些是我们到目前为止所拥有的文件和目录。

Procfile  locale  reddit_bot  setup.cfg
README.md  manage.py  requirements  utility
config  merge_production_dotenvs_in_dotenv.py requirements.txt
docs  pytest.ini  runtime.txt

步骤3.1:创建虚拟环境。

reddit_bot ➤ python3 -m venv ./venv

之后,您应该看到一个新创建的VENV文件夹。

Procfile  locale reddit_bot  setup.cfg
README.md  manage.py requirements  utility
config  merge_production_dotenvs_in_dotenv.py requirements.txt  venv
docs  pytest.ini  runtime.txt

步骤3.2:激活虚拟环境并安装所有依赖关系。

source venv/bin/activate

请注意,有一个(VENV)提示,这意味着您已经成功激活了虚拟环境。

注意:如果您尚未在您的Mac上安装Postgres数据库,则必须先安装。

在Mac上的Postgres安装上查看本文以获取更多详细信息。

从local.txt文件安装依赖项(与生产要求略有不同,因为它为您提供了更多的调试和测试工具。)

(venv) reddit_bot ➤
(venv) reddit_bot ➤ pip install -r requirements/local.txt

步骤3.3:创建本地数据库reddit_bot

(venv) reddit_bot ➤ createdb reddit_bot

之后,启动用于测试的Django Web服务器。

(venv) reddit_bot ➤ python manage.py runserver

您可能会看到以下内容。

Watching for file changes with StatReloader
INFO 2022-09-17 11:28:04,131 autoreload 17789 4335895936 Watching for file changes with StatReloader
Performing system checks...

System check identified no issues (0 silenced).

You have 28 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): account, admin, auth, contenttypes, sessions, sites, socialaccount, users.
Run 'python manage.py migrate' to apply them.
September 17, 2022 - 11:28:04
Django version 3.2.15, using settings 'config.settings.local'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
[17/Sep/2022 11:28:16] "GET / HTTP/1.1" 200 13541
[17/Sep/2022 11:28:16] "GET /static/debug_toolbar/css/toolbar.css HTTP/1.1" 200 11815
[17/Sep/2022 11:28:16] "GET /static/css/project.css HTTP/1.1" 200 228
[17/Sep/2022 11:28:16] "GET /static/debug_toolbar/css/print.css HTTP/1.1" 200 43
[17/Sep/2022 11:28:16] "GET /static/debug_toolbar/js/toolbar.js HTTP/1.1" 200 12528
[17/Sep/2022 11:28:16] "GET /static/js/project.js HTTP/1.1" 200 45
[17/Sep/2022 11:28:16] "GET /static/debug_toolbar/js/utils.js HTTP/1.1" 200 4479
[17/Sep/2022 11:28:16] "GET /static/images/favicons/favicon.ico HTTP/1.1" 200 8348

由于数据库是全新的,因此我们需要使用一些内置Django表初始化它。

(venv) reddit_bot ➤ python manage.py migrate

迁移完成后,重新启动服务器。

(venv) reddit_bot ➤ python manage.py migrate

打开您喜欢的浏览器(我正在使用最新的Chrome)并访问Localhost:8000请确保您可以成功地看到该网站。

恭喜您完成了设置本地Django服务器;接下来,让我们设置我们的Reddit帐户并安装Reddit API库:Praw。

注册Reddit应用程序并安装Praw Library
我们假设您已经有一个REDDIT帐户来设置Reddit开发人员帐户。如果没有,只需访问https://reddit.com并创建一个,然后回来。

您必须先注册Reddit上适当类型的申请。

然后访问https://www.reddit.com/prefs/apps/

注意:有时候,访问上页时,我会有一些页面重定向问题;如果发生这种情况,请尝试访问以下内容:

https://old.reddit.com/prefs/apps/

向下滚动,然后单击创建另一个应用程序...按钮

reddit监视教程|注册申请

对于您的应用程序的名称,任何内容都应该很好

应用程序类型:由于我们将在后端构建运行的东西,因此请选择脚本。

和重定向的URI,输入http://localhost:8000

然后单击创建应用按钮以完成此步骤。

reddit监视应用客户端秘密| segue.co

我们需要两个令牌运行:

  1. 客户端ID:个人使用脚本下方的一个

  2. 客户秘密:秘密右边的一个

最后,我们需要安装Praw库,并尝试使用最后一步的秘密键与Reddit连接。

(venv) reddit_bot ➤ pip install praw

接下来,我们将praw附加到依赖项上(否则,当我们部署到生产时,服务将无法正常工作:

(venv) reddit_bot ➤ pip freeze | grep praw >> requirements/base.txt

不保存敏感信息,例如在git存储库中的应用程序秘密令牌,因此,让我们在项目的根部创建一个新文件.env,以便我们可以在本地计算机上访问应用程序秘密。

(venv) reddit_bot ➤ vim .env

从最后一步替换秘密和客户端。

对于用户代理,这并不重要。要确切找出您的用户代理是什么,只需转到Google并键入“查找我的用户代理”,然后将其复制并粘贴到.env文件中。

接下来,请确保将.ENV添加到未通过编辑.gitignore文件的文件列表中。

(venv) reddit_bot ➤ vim .gitignore

并将.env添加到文件中;之后,运行以下以加载环境变量。

测试您的reddit连接。在您的终端中,运行以下内容:

(venv) reddit_bot ➤ source .env

我们还需要将变量加载到Django的环境变量中。

打开config/settings/local.py文件(我正在使用pycharm),并添加以下内容:

# Reddit settings:
REDDIT_SECRET=env('SECRET')
REDDIT_CLIENT_ID=env('CLIENT_ID')
REDDIT_USERAGENT=env('REDDIT_USERAGENT')

reddit监视django load reddit应用程序秘密| segue.co

在终端中

启动Django控制台

(venv) reddit_bot ➤ python manage.py shell


In [1]: from django.conf import settings

In [2]: import praw

In [3]: reddit = praw.Reddit(
   ...:     client_id=settings.REDDIT_CLIENT_ID,
   ...:     client_secret=settings.REDDIT_SECRET,
   ...:     user_agent=settings.REDDIT_USERAGENT,
   ...: )

如果您没有收到任何错误消息,则意味着您已经成功地通过Praw创建了Reddit实例。

接下来,让我们运行一个简单的任务来检查连接。

In [4]: for submission in reddit.subreddit("marketing").hot(limit=10):
   ...:     print(submission.title)
   ...:
New Job Listings
Sorry if this isn't allowed, but I recently created a subreddit focused on the business side of art, and would love for people to go there and share their knowledge and experiences.
I read privacy and policies of Tiktok, IG and Other Platforms. Here’s what I learned about Social Media Platforms!
Has anyone actually worked with an impressive agency?
How to bring first customers to shop?
Facebook ad numbers don't ad up
Beginning my career in marketing, looking to go in to an Agency
I hate digital marketing - help me find a new role
Where to start for ecom store?
Making a website

如果您看到与上述类似的东西,恭喜,您已经成功地与Reddit的官方API联系了,并从R/Marketing中检索了十大热门帖子,恭喜!

带正则表达式的关键字监视
假设您经营着Facebook广告代理商,而您的目标客户是Facebook广告的新手,那么如果您可以回应Reddit上对Facebook广告有疑问的人吗?

插入并加入Reddit的对话将有所帮助:

  1. 建立您作为Facebook广告专家的声誉;

  2. 将有关您服务的消息传播到世界上最大的在线社区,并吸引您网站的优质流量;

  3. 如果您获得了足够的选票,您的回复可能会成为改进SEO

  4. 的反向链接

在本文中,我们将向您展示如何找到标题包含“ Facebook”一词的任何帖子。

当然,您可以继续优化此匹配规则并制定自己的解决方案。

对于更高级的匹配算法,请随时根据最先进的NLP语义搜索查看Segue的Reddit潜在客户生成引擎。

再次,我们首先打开Django控制台。

(venv) reddit_bot ➤ python manage.py shell

django控制台的内部:

import praw
from django.conf import settings

import re # new, the python regular expression library

keyword =  "facebook"

reddit = praw.Reddit(
     client_id=settings.REDDIT_CLIENT_ID,
     client_secret=settings.REDDIT_SECRET,
     user_agent=settings.REDDIT_USERAGENT,
)

for submission in reddit.subreddit("marketing").hot(limit=100): # we are searching 100 hottest posts on the marketing subreddit
    if re.search(keyword, submission.title, re.IGNORECASE): # new, notice we are ignoring the case sensitivity
        print(submission.title)

您的结果可能与我的结果有所不同(我们在2022年9月18日进行了此搜索)。

In [2]: for submission in reddit.subreddit("marketing").hot(limit=100):
   ...:     if re.search(keyword, submission.title, re.IGNORECASE): # new, notice we are ignoring the case sensitivity
   ...:         print(submission.title)
   ...:
Facebook ad numbers don't ad up
Facebook & Instagram Ads campaign Setup
Measuring the impact of Facebook
How many interests is too many Interest - Facebook Ads


We've found four discussions about Facebook without too much work. How awesome is it!

Let's save those results and other metadata such as URLs, post date, and content into a database so we don't lose them.

将数据持续到Postgres数据库。
让我们首先创建一个新应用

# In the root dir of your project
(venv) reddit_bot ➤ django-admin startapp reddit

注意:我们还需要将新创建的应用程序移至Reddit_bot子目录。由于Cookie-Cutter构造了我们的项目,因此此步骤很重要。

mv reddit ./reddit_bot

接下来,让我们更新apps.py配置文件。

默认名称为“ reddit”,我们需要将其更新为“ reddit_bot.reddit”,因为我们已经将其从根目录移至子目录。

,不要忘记将此应用程序包含在base.py配置文件中。

现在让我们打开型号。py文件并添加我们的第一类。

class Lead(models.Model):
    post_id = models.CharField(max_length=10) # Original post id
    title = models.TextField()
    content = models.TextField()
    posted_at = models.DateTimeField()
    url = models.URLField(max_length=500)

在命令行中,让我们安装应用程序和模型并进行迁移。

(venv) reddit_bot ➤ python manage.py makemigrations
Migrations for 'reddit':
  reddit_bot/reddit/migrations/0001_initial.py
    - Create model Lead

(venv) reddit_bot ➤ python manage.py migrate
Operations to perform:
  Apply all migrations: account, admin, auth, contenttypes, reddit, sessions, sites, socialaccount, users
Running migrations:
  Applying reddit.0001_initial... OK

接下来,让我们创建一个命令行脚本以执行关键字匹配并将结果保存到领先模型中。

对于此脚本,让我们称其为leds_finder.py,然后将其放在reddit/management/commands文件夹下。

首先,我们需要创建两个文件夹:

# Move to the reddit app directory
(venv) reddit_bot ➤ cd reddit_bot/reddit
(venv) reddit ➤ mkdir management
(venv) reddit ➤ mkdir management/commands

# Inside reddit_bot/reddit_bot/reddit/management/commands/lead_finder.py file
import datetime as DT
import re

import praw
from django.conf import settings
from django.core.management.base import BaseCommand
from django.utils import timezone
from django.utils.timezone import make_aware

from reddit_bot.reddit.models import Lead

KEYWORD = "facebook"
SUBREDDIT = 'marketing'

reddit = praw.Reddit(
    client_id=settings.REDDIT_CLIENT_ID,
    client_secret=settings.REDDIT_SECRET,
    user_agent=settings.REDDIT_USERAGENT,
)

def convert_to_ts(unix_time):
    try:
        ts = make_aware(DT.datetime.fromtimestamp(unix_time))
        return ts
    except:
        print(f"Converting utc failed for {unix_time}")
        return None


def populate_lead(keyword, subreddit):
    for submission in reddit.subreddit(subreddit).hot(limit=100):
        if re.search(keyword, submission.title, re.IGNORECASE):
            if not Lead.objects.filter(post_id = submission.id):
                Lead.objects.create(post_id=submission.id,
                                    title=submission.title,
                                    url=submission.permalink,
                                    content=submission.selftext,
                                    posted_at=convert_to_ts(submission.created_utc))


class Command(BaseCommand):
    help = 'Populating leads'

    def handle(self, *args, **kwargs):
        try:
            current_time = timezone.now()
            self.stdout.write(f'Populating leads at {(current_time)}')
            populate_lead(KEYWORD, SUBREDDIT)
        except BaseException as e:
            current_time = timezone.now().strftime('%X')
            self.stdout.write(self.style.ERROR(f'Populating feeds failed at {current_time} because {str(e)}'))

        current_time = timezone.now()
        self.stdout.write(self.style.SUCCESS(f'Successfully populated new leads at {current_time}'))
        return

一些解释:

此脚本有3个部分,转换_TO_TS函数将UNIX时间转换为人类可读格式。当首先以大整数的格式创建帖子时,reddit存储了时间戳。

populate_lead在我们的上一节中使用相同的逻辑并保存新的引线(如果尚未保存在我们的表中,请记住,我们将post_id执行为我们的领先模型定义中的主要键)

)最后,我们创建了一个命令类,以便可以在命令行中执行populate_lead。还有其他方法可以在命令行上执行脚本,但是我认为,这种方式更像是Django样式。

最后,我们可以尝试执行脚本并填充一些线索。

(venv) reddit_bot ➤ python manage.py lead_finder
Populating leads at 2022-09-18 17:50:35.045981+00:00
Successfully populated new leads at 2022-09-18 17:50:36.558052+00:00

让我们打开Django控制台以验证结果已成功保存。

from reddit_bot.reddit.models import Lead

for lead in Lead.objects.all():
        print(f'''title: {lead.title}\nposted_at:{lead.posted_at}\nurl: {lead.url}\n''')



title: Facebook ad numbers don't ad up
posted_at:2022-09-17 21:14:24+00:00
url: /r/marketing/comments/xgxv9c/facebook_ad_numbers_dont_ad_up/

title: Facebook & Instagram Ads campaign Setup
posted_at:2022-09-17 08:01:38+00:00
url: /r/marketing/comments/xgghl9/facebook_instagram_ads_campaign_setup/

title: Measuring the impact of Facebook
posted_at:2022-09-16 20:49:14+00:00
url: /r/marketing/comments/xg2kbi/measuring_the_impact_of_facebook/

title: How many interests is too many Interest - Facebook Ads
posted_at:2022-09-16 01:32:28+00:00
url: /r/marketing/comments/xfdwsg/how_many_interests_is_too_many_interest_facebook/

我们走了。所有四个线索都成功地持续了!

领导报告视图
很酷,我们可以在控制台中看到数据,但是如果我们可以从浏览器中查看表中的潜在客户,这将变得更容易。

在view.py文件中,让我们创建一个listView。

#inside reddit_bot/reddit_bot/reddit/views.py

from django.views.generic import ListView

from .models import Lead

# Create your views here.
class LeadView(ListView):
    model = Lead
    template_name = 'lead_list.html'

lead_view = LeadView.as_view()

我们还需要在reddit应用下的新目录中创建一个名为模板的新目录中的html文件'leds_list.html'。

{% extends 'base.html' %}

    {% block content %}
        <table class="table table-striped">
        <thead>
        <tr>
        <th scope="col">ID</th>
        <th scope="col">Title</th>
        <th scope="col">Posted At</th>
        <th scope="col">Content</th>
        </tr>
        </thead>
        <tbody>

        {% for lead in object_list %}
            <tr>
            <th scope="row">{{ lead.post_id }}</th>
            <td><a href="https://reddit.com{{ lead.url }}"> {{ lead.title }}</a></td>
            <td>{{ lead.posted_at }}</td>
            <td>{{ lead.content }}</td>
            </tr>
        {% endfor %}

        </tbody>
        </table>

    {% endblock %}

接下来,我们需要添加一个URL路径来访问此视图。

创建一个新文件:reddit应用下的urls.py

内部reddit_bot/reddit_bot/reddit/urls.py

from django.urls import path

from reddit_bot.reddit.views import lead_view

app_name = "reddit"

urlpatterns = [

    path("leads/", view=lead_view, name="leads"),

]

最后,我们必须在项目级别上包含Reddit应用程序的URL文件。

最后一步:检查页面,打开浏览器,然后访问:http://localhost:8000/reddit/leads/

,如果您单击标题,您将被重定向到Reddit帖子页面,您可以在其中与目标客户互动。那有多酷!

安排一个cron工作以定期检查reddit。
我们快要完成了,如果您像我一样,我们喜欢自动化我们的任务;我们如何安排自动运行的工作?

这非常容易。

在端子中,类型 crontab -e 并输入。

添加以下行(您需要编辑reddit_bot django项目的路径)

1 * * * * cd ~/reddit_bot; source venv/bin/activate; source .env; python manage.py lead_finder >/tmp/stdout.log 2>/tmp/stderr.log

例如,如果现在是11:35 AM,则每小时每小时运行,下次这项工作将在12:01 pm和13:01 pm进行。<<<<<<<< /p>

当然,您可以更改最适合您的时间表。您可以使用以下内容来自定义您的cron作业。

https://crontab.guru/

结论
我们已经完成了如何使用Python设置自己的Reddit关键字监视。

如果您想使用我们生产的Reddit监控服务,请随时查看
segue.co