首页 > 解决方案 > PRAW:你能在同一条消息中从两个单独的关键字列表中接收数据吗?

问题描述

我目前有一个 reddit 机器人,它从 subreddit 接收关键字,然后在 Slack 上向我发送通知。

向我发送通知的当前代码是

for kw in keywords:
                if kw.lower() in comment.body.lower():  # case insensitive check
                    already_alerted_submissions.append(comment.submission.id)
                    msg = '[Keyword *{0}* detected](http://www.reddit.com{1})'.format(
                        kw, comment.permalink)
                    slack_data = {'text': msg, 'mrkdwn': True}

所以它目前正在从

keywords = ['camera', 'nikon', 'canon', 'campus']  # case insensitive

我想知道文件中是否可以有两个单独的关键字列表,如下所示

keywords = ['camera', 'nikon', 'canon', 'campus']  # case insensitive
keywords_color = ['red', 'blue', 'green', 'black']  # case insensitive

如果在一个线程中检测到“相机”这个词,它会像现在一样发布一条消息。

但是,如果在同一条评论中,它会从关键字 AND 和 keywords_color 中检测到一个关键字

它可以在 slack 中发布相同的消息,但另一行显示类似于“检测到颜色”的内容

因此,在上面的示例中,slack 中的消息将如下所示。

1. [Keyword *camera* detected]
(http://www.reddit.com/r/camera/comments/9yg8mt/goodcameras
I just got a great CAMERA today, it is awesome

或者,如果它同时检测到“keywords”和“keywords_color”,它将如下所示

2. 1. [Keyword *camera* detected]
(http://www.reddit.com/r/camera/comments/9yg8mt/goodcameras
I just got a great CAMERA today, it is a RED one and its awesome
**Colour was detected**

这可能吗?任何帮助,将不胜感激!

该文件的完整脚本在这里:

def main():

    alerted_comments = get_list_from_pickle('alerted_comments.pickle')

    try:

        for comment in comment_stream:
            if comment.id in alerted_comments:
                continue

            if comment.author:  # if comment author hasn't deleted
                if comment.author.name in ignore_users:
                    continue

            for kw in keywords:
                if kw.lower() in comment.body.lower():  # case insensitive check
                    alerted_comments.append(comment.id)

                    while len(alerted_comments) > 100:
                        del alerted_comments[0]

                    with open('alerted_comments.pickle', 'wb') as fp:
                        pickle.dump(alerted_comments, fp)

            for kw in keywords:
                if kw.lower() in comment.body.lower():  # case insensitive check
                    alerted_comments.append(comment.submission.id)
                    msg = '[Keyword *{0}* detected](http://www.reddit.com{1})'.format(
                        kw, comment.permalink)
                    slack_data = {'text': msg, 'mrkdwn': True}

                    response = requests.post('https://hooks.slack.com/services/BE72P09A9/xxxxxxxxx78',
                                             data=json.dumps(slack_data), headers={'Content-Type': 'application/json'})
                    if response.status_code != 200:
                        raise ValueError('Request to slack returned an error %s, the response is:\n%s' % (
                            response.status_code, response.text))

    except Exception as e:
        print('There was an error: ' + str(e))
        sleep(60)  # wait for 60 seconds before restarting
        main()

if __name__ == '__main__':
    main()

标签: pythonpython-3.x

解决方案


这是未经测试的,但你去:

import json
import time

import requests


class SlackError(Exception):
    # This isn't quite how I would handle this, so for now it's
    # just a hint of more to learn.
    pass


MSG_TEMPLATE = """[Keyword *{keyword}* detected]
(https://www.reddit.com{permalink})
{comment_body}"""

SLACK_WEBHOOK = 'https://hooks.slack.com/services/BE72P09A9/xxxxxxxxx78'


def main(*, save_path):
    keywords = ...
    color_keywords = ...
    ignore_users = ...

    comment_stream = ...

    with open(save_path, 'r') as fp:
        alerted_comments = json.load(fp)

    for comment in comment_stream:
        if comment.id in alerted_comments:
            continue

        if comment.author:  # if comment author hasn't deleted
            if comment.author.name in ignore_users:
                continue

        if any(kw.lower() in comment.body.lower() for kw in keywords):
            found_kws = [kw for kw in keywords if kw.lower() in comment.body.lower()]

            msg = MSG_TEMPLATE.format(
                keyword=found_kws[0],
                permalink=permalink,
                comment_body=comment.body
            )

            if any(kw.lower() in comment.body.lower() for kw in color_keywords):
                msg += "\nColour was detected"

            slack_data = {'text': msg, 'mrkdwn': True}

            response = requests.post(
                SLACK_WEBHOOK,
                data=json.dumps(slack_data),
                headers={'Content-Type': 'application/json'}
            )

            if response.status_code == 200:
                # Moving this here so you don't miss a comment
                # because of an error. It does mean other errors
                # could potentially cause a repeat message. There
                # are ways to handle that.

                alerted_comments.append(comment.id)

                if len(alerted_comments) > 100:
                    alerted_comments = alerted_comments[-100:]

                with open(save_path, 'w') as fp:
                    json.dump(alerted_comments, fp)
            else:
                # You'll probably want to be more discerning than "not 200",
                # but that's fine for now.
                raise SlackError(
                    'Request to Slack returned an error %s, the response is:\n%s' % (
                        response.status_code, response.text))

if __name__ == '__main__':
    while True:
        try:
            main(save_path='alerted_comments.json')
        except Exception as e:
            print('There was an error: {}'.format(str(e)))
            time.sleep(60)  # wait for 60 seconds before restarting

如果您有任何问题,请告诉我。


推荐阅读