This is old, but posting here for reference since spammers seem to be using this method a bit more. Could be altered for XF2.x as needed, or extrapolated to other uses.
To keep users who are banned from showing up on profile pages of other members as followers:
Find this in template member_view
<div class="primaryContent avatarHeap">
<ol>
<xen:foreach loop="$followers" key="$followUserId" value="$followUser">
<li>
<xen:avatar user="$followUser" size="s" text="{$followUser.username}" class="Tooltip" title="{$followUser.username}" itemprop="contact" />
</li>
</xen:foreach>
</ol>
</div>
add in the bolded parts:
<div class="primaryContent avatarHeap">
<ol>
<xen:foreach loop="$followers" key="$followUserId" value="$followUser">
<xen:if is="!{$followUser.is_banned}">
<li>
<xen:avatar user="$followUser" size="s" text="{$followUser.username}" class="Tooltip" title="{$followUser.username}" itemprop="contact" />
</li>
</xen:if>
</xen:foreach>
</ol>
</div>
This doesn't alter the database query, doesn't require code changes in files or an add on. But you can hide the display of the banned user from profiles. The count of members following a given member will be off from what's shown.
Why is this needed? Spammers are getting in after multiple levels of checks and settings, registering with disgusting names, following hundreds of people before posting even once. Once they are caught and banned, cleaned, their posts are gone, profile hidden, but their follows are still present, forcing hundreds of members to look at that name on their profile page forever. Only way to fully remove is delete the banned account, which we prefer to keep in system for cross checks and IP banning etc.
I know XF1.x is EoL, and not sure how XF2 handles. But, logic is there above in case needed. I'm sure a more elegant solution could be done.