# Comment Parsing

A common task for many bots and scripts is to parse a submission´s comments. In this tutorial we will go over how to do that as well as talking about comments in general. To illustrate the problems, we’ll write a small script that replies to any comment that contains the text “Hello”. Our reply will contain the text ” world!”.

## Submission Comments

As usual, we start by importing PRAW and initializing our contact with reddit.com. We also get a `Submission` object, where our script will do its work.

    >>> import praw
    >>> r = praw.Reddit('Comment Scraper 1.0 by u/_Daimon_ see '
    ...                 'https://praw.readthedocs.org/en/latest/'
    ...                 'pages/comment_parsing.html')
    >>> submission = r.get_submission(submission_id='11v36o')

After getting the `Submission` object we retrieve the comments and look through them to find those that match our criteria. Comments are stored in the attribute `comments` in a comment forest, with each tree root a toplevel comment. E.g., the comments are organized just like when you visit the submission via the website. To get to a lower layer, use `replies` to get the list of replies to the comment. Note that this may include `MoreComments` objects and not just `Comment`.

    >>> forest_comments = submission.comments

As an alternative, we can flatten the comment forest to get a unordered list with the function `praw.helpers.flatten_tree()`. This is the easiest way to iterate through the comments and is preferable when you don’t care about a comment’s place in the comment forest. We don’t, so this is what we are going to use.

    >>> flat_comments = praw.helpers.flatten_tree(submission.comments)

To find out whether any of those comments contains the text we are looking for, we simply iterate through the comments.

    >>> for comment in flat_comments:
    ...     if comment.body == "Hello":
    ...         reply_world(comment)

Our program is going to make comments to a submission. If it has bugs, then it might flood a submission with replies or post gibberish. This is bad. So we test the bot in r/test before we let it loose on a “real” subreddit. As it happens, our bot as described so far contains a bug. It doesn’t test if we’ve already replied to a comment before replying. We fix this bug by storing the content_id of every comment we’ve replied to and test for membership of that list before replying. Just like in Writing a reddit Bot.

## The number of comments

When we load a submission, the comments for the submission are also loaded, up to a maximum, just like on the website. At reddit.com, this max is 200 comments. If we want more than the maximum number of comments, then we need to replace the `MoreComments` with the `Comment`s they represent. We use the `replace_more_comments()` method to do this. Let’s use this function to replace all `MoreComments` with the `Comment`s they represent, so we get all comments in the thread.

    >>> submission.replace_more_comments(limit=None, threshold=0)
    >>> all_comments = submission.comments

The number of `MoreComments` PRAW can replace with a single API call is limited. Replacing all `MoreComments` in a thread with many comments will require many API calls and so take a while due to API delay between each API call as specified in the api guidelines.

## Getting all recent comments to a subreddit or everywhere

We can get comments made to all subreddits by using `get_comments()` and setting the subreddit argument to the value “all”.

    >>> import praw
    >>> r = praw.Reddit('Comment parser example by u/_Daimon_')
    >>> all_comments = r.get_comments('all')

The results are equivalent to /r/all/comments.

We can also choose to only get the comments from a specific subreddit. This is much simpler than getting all comments made to a reddit and filtering them. It also reduces the load on the reddit.

    >>> subreddit = r.get_subreddit('python')
    >>> subreddit_comments = subreddit.get_comments()

The results are equivalent to r/python/comments.

You can use multi-reddits to get the comments from multiple subreddits.

    >>> multi_reddits = r.get_subreddit('python+learnpython')
    >>> multi_reddits_comments = multi_reddits.get_comments()

Which is equivalent to r/python+learnpython/comments.

## The full program

    import praw

    r = praw.Reddit('Comment Scraper 1.0 by u/_Daimon_ see '
                    'https://praw.readthedocs.org/en/latest/'
                    'pages/comment_parsing.html')
    r.login('bot_username', 'bot_password')
    submission = r.get_submission(submission_id='11v36o')
    flat_comments = praw.helpers.flatten_tree(submission.comments)
    already_done = set()
    for comment in flat_comments:
        if comment.body == "Hello" and comment.id not in already_done:
            comment.reply(' world!')
            already_done.add(comment.id)

## [deleted] comments

When a comment is deleted, in most cases, that comment will not be viewable with a browser nor the API. However, if a comment is made, and then a reply to that comment is made, and then the original comment is deleted, that comment will have its `body` and `author` attributes be `NoneType` via the API. The same goes with removed comments, unless the authenticated account is a mod of the subreddit whose comments you are getting. If you are a mod, and said comments are removed comments, they are left intact.

If a comment is made and then the account that left that comment is deleted, the comment body is left intact, while the `author` attribute becomes `NoneType`.