Julia, 90 characters
Unlike the original solution (below), this uses mathematics to determine the solution.
mapfoldl(collect,hcat,split(s,"\n")) (written above with
\n replaced with an actual newline to save characters) converts the string into a 2d array of characters.
map(i->i∈"!|.\":"?-1:i∈"()_@\$&",...) creates an array of numbers, with 1 if the character is a cloud, -1 if the character is rain, and 0 otherwise.
cumsum(...') calculates the cumulative sums of the rows (would normally be written
cumsum(...,2), but since we don't care about orientation from this point on, transposing only costs one character), and then
all(... .>-1) checks for a negative number - negatives will only occur if a rain character appears without being preceded by a cloud character.
139 136 characters
This function first transposes the text so that rows become columns and vice-versa. Note that newlines are present in the code in the form of actual newlines, to save one character per instance.
The function then iteratively replaces cloud/droplet pairs with spaces, and once all such pairs are removed, it returns true if there are any droplets remaining and false otherwise.
r"[()_@$&](.*?)[!|.\":]" - this is a regex that will match cloud/droplet pairs in a lazy manner, with group 1 containing everything between cloud and droplet. Then
s"\g<1>" tells it to remove the matched cloud and droplets, but keep the stuff in between (necessary as it may contain clouds) - the
\g<1> is whatever was matched in group 1 of the regex.
∩("!|.\":",t)== will generate the intersection of the droplet characters with the final string, and if it's empty, then none of the droplet characters are present, and it's raining.