【问题标题】:Python - possible to only send message when keyword is detected in BOTH keyword lists?Python - 只能在两个关键字列表中检测到关键字时发送消息?
【发布时间】:2018-11-24 01:40:22
【问题描述】:

我有一个 python 脚本,它从关键字列表keywords = ['camera', 'nikon'] 中检测一个关键字,然后向 Slack 发送一条消息,如下所示

检测到关键字相机

'Reddit 帖子网址'

'包含关键字的reddit评论'

如果脚本从第二个关键字列表color_keywords = ['red', 'blue'] 中检测到一个关键字,那么它会发布以下内容

检测到关键字相机

'Reddit 帖子网址'

'包含关键字的reddit评论'

检测到颜色

我的问题是,我是否能够以某种方式拥有脚本,以便仅在找到每个关键字列表中的关键字时才发送消息? 所以如果它只从第一个列表中找到一个关键字,它将被忽略,如果它从第二个列表中找到一个,它也将被忽略。但如果它从 BOTH 列表中找到一个关键字,它会将消息发送到 slack。

下面是我当前的代码

MSG_TEMPLATE = """Keyword *{keyword}* detected
https://www.reddit.com{permalink}
```{comment_body}```"""

keywords = ['camera', 'nikon', 'canon']  
color_keywords = ['blue', 'red']

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=comment.permalink,
                comment_body=comment.body
            )

            if any(kw.lower() in comment.body.lower() for kw in color_keywords):
                msg += "\n<!here> *A color was detected*"

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

            response = requests.post('https://hooks.slack.com/services/TB7AH6U2G/xxxxxxx/0KOjl9251TZExxxxxxxx',
                                             data=json.dumps(slack_data), headers={'Content-Type': 'application/json'})

任何帮助将不胜感激!

【问题讨论】:

    标签: python python-3.x python-requests slack-api praw


    【解决方案1】:

    当然!为简洁起见,摘录以下代码:

    def find_keywords(comment, word_list):
        """:returns: List of matching keywords present in the comment, or the empty list"""
        return [word for word in word_list if word.lower() in comment.body.lower()]
    
    for comment in comment_stream:
        if not should_be_ignored(comment):
            found_kws = find_keywords(comment, keywords)
            found_colors = find_keywords(comment, color_keywords)
    
            if found_kws and found_colors:
                # At this point, we're guaranteed to have *both* one or more keywords *and* one or more colors
                send_message(comment, found_kws, found_colors)
    

    这里的关键见解是:您首先创建匹配列表,然后随后检查它们以决定是否要发送消息。在这种情况下,只有两个列表都不为空,您才会继续发送消息。

    (当然,should_be_ignored()send_message() 的实现留给读者作为练习。:))

    编辑:原代码的完整实现:​​

    def send_message(comment, keywords, colors):
        assert keywords and colors, "At this point, we should *only* be calling this function if we have at least one keyword and one color"
    
        MSG_TEMPLATE = """Keyword *{keyword}* and color *{color}* detected
        https://www.reddit.com{permalink}
        ```{comment_body}```"""
        msg = MSG_TEMPLATE.format(
            keyword=keywords[0],
            color=colors[0],
            permalink=comment.permalink,
            comment_body=comment.body
        )
        slack_data = {'text': msg, 'mrkdwn': True,}
        response = requests.post('https://hooks.slack.com/services/TB7AH6U2G/xxxxxxx/0KOjl9251TZExxxxxxxx',
                                 data=json.dumps(slack_data), headers={'Content-Type': 'application/json'})
    
    
    def should_be_ignored(comment, alerted):
        return comment.id in alerted or (comment.author and comment.author.name in ignore_users)
    
    
    def find_keywords(comment, word_list):
        """:returns: List of matching keywords present in the comment, or the empty list"""
        return [word for word in word_list if word.lower() in comment.body.lower()]
    
    
    keywords = ['camera', 'nikon', 'canon']  
    color_keywords = ['blue', 'red']
    
    with open(save_path, 'r') as fp:
        alerted_comments = json.load(fp)
    
    for comment in comment_stream:
        if not should_be_ignored(comment, alerted_comments):
            found_kws = find_keywords(comment, keywords)
            found_colors = find_keywords(comment, color_keywords)
    
            if found_kws and found_colors:
                # At this point, we're guaranteed to have *both* one or more keywords *and* one or more colors
                send_message(comment, found_kws, found_colors)
    

    请注意,我所做的一切(除了我们在发送消息之前同时具有颜色和关键字的新要求)是将您的一些业务逻辑提取到 @987654327 @ 和 send_message() 函数,希望能阐明代码主体的意图。这应该是您开始使用的示例的直接替代品。

    【讨论】:

    • 非常感谢您的回答!我一直在尝试将其格式化到我的代码中,但是在将它放在哪里以及从我当前的代码中取出什么方面遇到了麻烦?如果您能告诉我如何格式化它,是否有可能?抱歉,我是 python 新手,只是想了解一下它哈哈
    • @Vestipial,已编辑以包含您提供的完整示例。 :) 而且,呃...抱歉,我无法帮助自己进行重构...
    • 哈哈哇,非常感谢!,是的,我只是在 python 方面太新了,无法弄清楚哈哈。所以我已经将代码放入并尝试自己对所有内容进行排序,但现在我收到以下错误Traceback (most recent call last): File "fudbot-client.py", line 37, in &lt;module&gt; keyword=keywords[0], NameError: name 'keywords' is not defined 我尝试了一段时间弄乱代码,但没有帮助哈哈。我已经粘贴了整个脚本,也许我只是在某个地方漏掉了一行? pastebin.com/hj4JSyhR再次感谢您的详细帮助!
    • 看起来您的send_message() 上的缩进已损坏。 PasteBin 链接中的第 30 到 43 行都应该作为send_message() 定义的一部分缩进。您可能还希望将您的响应处理代码(第 75 行到第 93 行)移至 send_message()
    • 谢谢,我把它们都整理好了,现在我有一个奇怪的。我没有收到任何错误,脚本运行,显示 reddit 用户名(所以我猜它已登录),但脚本刚刚结束。但没有错误或任何东西。它只是跳回到奇怪的命令提示符? pastebin.com/m8tu2LRn
    猜你喜欢
    • 1970-01-01
    • 2020-05-18
    • 1970-01-01
    • 2021-07-03
    • 2021-04-12
    • 1970-01-01
    • 1970-01-01
    • 2013-09-08
    • 2016-10-31
    相关资源
    最近更新 更多