diff --git a/bleach/linkifier.py b/bleach/linkifier.py
index 6394c03..5d815f8 100644
--- a/bleach/linkifier.py
+++ b/bleach/linkifier.py
@@ -499,13 +499,11 @@ class LinkifyFilter(html5lib_shim.Filter):
                     # the tokens we're going to yield
                     in_a = False
                     token_buffer = []
-                    continue
-
                 else:
                     token_buffer.append(token)
-                    continue
+                continue
 
-            elif token['type'] in ['StartTag', 'EmptyTag']:
+            if token['type'] in ['StartTag', 'EmptyTag']:
                 if token['name'] in self.skip_tags:
                     # Skip tags start a "special mode" where we don't linkify
                     # anything until the end tag.
diff --git a/bleach/sanitizer.py b/bleach/sanitizer.py
index 262915a..9ba4c57 100644
--- a/bleach/sanitizer.py
+++ b/bleach/sanitizer.py
@@ -267,8 +267,8 @@ class BleachSanitizerFilter(html5lib_shim.SanitizerFilter):
 
         return super(BleachSanitizerFilter, self).__init__(source, **kwargs)
 
-    def __iter__(self):
-        for token in html5lib_shim.Filter.__iter__(self):
+    def sanitize_stream(self, token_iterator):
+        for token in token_iterator:
             ret = self.sanitize_token(token)
 
             if not ret:
@@ -280,6 +280,40 @@ class BleachSanitizerFilter(html5lib_shim.SanitizerFilter):
             else:
                 yield ret
 
+    def merge_characters(self, token_iterator):
+        """Merge consecutive Characters tokens in a stream"""
+        characters_buffer = []
+
+        for token in token_iterator:
+            if characters_buffer:
+                if token['type'] == 'Characters':
+                    characters_buffer.append(token)
+                    continue
+                else:
+                    # Merge all the characters tokens together into one and then
+                    # operate on it.
+                    new_token = {
+                        'data': ''.join([char_token['data'] for char_token in characters_buffer]),
+                        'type': 'Characters'
+                    }
+                    characters_buffer = []
+                    yield new_token
+
+            elif token['type'] == 'Characters':
+                characters_buffer.append(token)
+                continue
+
+            yield token
+
+        new_token = {
+            'data': ''.join([char_token['data'] for char_token in characters_buffer]),
+            'type': 'Characters'
+        }
+        yield new_token
+
+    def __iter__(self):
+        return self.merge_characters(self.sanitize_stream(html5lib_shim.Filter.__iter__(self)))
+
     def sanitize_token(self, token):
         """Sanitize a token either by HTML-encoding or dropping.
 

diff --git a/tests/test_clean.py b/tests/test_clean.py
index b543cdf..5322767 100644
--- a/tests/test_clean.py
+++ b/tests/test_clean.py
@@ -58,6 +58,7 @@ def test_html_is_lowercased():
         '<a href="http://example.com">foo</a>'
     )
 
+
 def test_invalid_uri_does_not_raise_error():
     assert clean('<a href="http://example.com]">text</a>') == '<a>text</a>'
 
diff --git a/tests/test_linkify.py b/tests/test_linkify.py
index 876cb84..eeea3e3 100644
--- a/tests/test_linkify.py
+++ b/tests/test_linkify.py
@@ -4,7 +4,8 @@ import pytest
 from six.moves.urllib_parse import quote_plus
 
 from bleach import linkify, DEFAULT_CALLBACKS as DC
-from bleach.linkifier import Linker
+from bleach.linkifier import Linker, LinkifyFilter
+from bleach.sanitizer import Cleaner
 
 
 def test_empty():
@@ -656,3 +657,20 @@ class TestLinkify:
 
         with pytest.raises(TypeError):
             linkify(no_type)
+
+
+@pytest.mark.parametrize('text, expected', [
+    ('abc', 'abc'),
+    ('example.com', '<a href="http://example.com">example.com</a>'),
+    (
+        'http://example.com?b=1&c=2',
+        '<a href="http://example.com?b=1&amp;c=2">http://example.com?b=1&amp;c=2</a>'
+    ),
+    (
+        'link: https://example.com/watch#anchor',
+        'link: <a href="https://example.com/watch#anchor">https://example.com/watch#anchor</a>'
+    )
+])
+def test_linkify_filter(text, expected):
+    cleaner = Cleaner(filters=[LinkifyFilter])
+    assert cleaner.clean(text) == expected

LinkifyFilter not working for URLs with ampersands
Example with bleach 2.1.3:

```
from bleach import Cleaner
from bleach.linkifier import LinkifyFilter

url1 = 'http://a.co?b=1&c=2'
url2 = 'http://a.co?b=1&amp;c=2'

cleaner = Cleaner(filters=[LinkifyFilter])
cleaner.clean(url1)
cleaner.clean(url2)
```

Both result in `<a href="http://a.co?b=1">http://a.co?b=1</a>&amp;c=2`

tests/test_linkify.py::test_linkify_filter[http://example.com?b=1&c=2-<a
tests/test_clean.py::test_clean_idempotent tests/test_clean.py::test_only_text_is_cleaned tests/test_clean.py::test_empty tests/test_clean.py::test_content_has_no_html tests/test_clean.py::test_content_has_allowed_html[an tests/test_clean.py::test_content_has_allowed_html[another tests/test_clean.py::test_html_is_lowercased tests/test_clean.py::test_invalid_uri_does_not_raise_error tests/test_clean.py::test_comments[<!-- tests/test_clean.py::test_comments[<!--open tests/test_clean.py::test_comments[<!--comment-->text-True-text] tests/test_clean.py::test_comments[<!--comment-->text-False-<!--comment-->text] tests/test_clean.py::test_comments[text<!-- tests/test_clean.py::test_comments[text<!--comment-->-True-text] tests/test_clean.py::test_comments[text<!--comment-->-False-text<!--comment-->] tests/test_clean.py::test_invalid_char_in_tag tests/test_clean.py::test_unclosed_tag tests/test_clean.py::test_nested_script_tag tests/test_clean.py::test_bare_entities_get_escaped_correctly[an tests/test_clean.py::test_bare_entities_get_escaped_correctly[tag tests/test_clean.py::test_character_entities_handling[&amp;-&amp;] tests/test_clean.py::test_character_entities_handling[&nbsp;-&nbsp;] tests/test_clean.py::test_character_entities_handling[&nbsp; tests/test_clean.py::test_character_entities_handling[&lt;em&gt;strong&lt;/em&gt;-&lt;em&gt;strong&lt;/em&gt;] tests/test_clean.py::test_character_entities_handling[&amp;is tests/test_clean.py::test_character_entities_handling[cool tests/test_clean.py::test_character_entities_handling[&&amp; tests/test_clean.py::test_character_entities_handling[&amp; tests/test_clean.py::test_character_entities_handling[this tests/test_clean.py::test_character_entities_handling[http://example.com?active=true&current=true-http://example.com?active=true&amp;current=true] tests/test_clean.py::test_character_entities_handling[<a tests/test_clean.py::test_character_entities_handling[&xx;-&xx;] tests/test_clean.py::test_character_entities_handling[&#39;-&#39;] tests/test_clean.py::test_character_entities_handling[&#34;-&#34;] tests/test_clean.py::test_character_entities_handling[&#123;-&#123;] tests/test_clean.py::test_character_entities_handling[&#x0007b;-&#x0007b;] tests/test_clean.py::test_character_entities_handling[&#x0007B;-&#x0007B;] tests/test_clean.py::test_character_entities_handling[&#-&amp;#] tests/test_clean.py::test_character_entities_handling[&#<-&amp;#&lt;] tests/test_clean.py::test_character_entities_handling[&#39;&#34;-&#39;&#34;] tests/test_clean.py::test_stripping_tags[a tests/test_clean.py::test_stripping_tags[<p><a tests/test_clean.py::test_stripping_tags[<p><span>multiply tests/test_clean.py::test_stripping_tags[<ul><li><script></li></ul>-kwargs4-<ul><li></li></ul>] tests/test_clean.py::test_stripping_tags[<isindex>-kwargs6-] tests/test_clean.py::test_stripping_tags[Yeah tests/test_clean.py::test_stripping_tags[<sarcasm>-kwargs8-] tests/test_clean.py::test_stripping_tags[</sarcasm>-kwargs9-] tests/test_clean.py::test_stripping_tags[</ tests/test_clean.py::test_stripping_tags[Foo tests/test_clean.py::test_stripping_tags[Favorite tests/test_clean.py::test_stripping_tags[</3-kwargs14-&lt;/3] tests/test_clean.py::test_escaping_tags[<img tests/test_clean.py::test_escaping_tags[<script>safe()</script>-&lt;script&gt;safe()&lt;/script&gt;] tests/test_clean.py::test_escaping_tags[<style>body{}</style>-&lt;style&gt;body{}&lt;/style&gt;] tests/test_clean.py::test_escaping_tags[<ul><li><script></li></ul>-<ul><li>&lt;script&gt;</li></ul>] tests/test_clean.py::test_escaping_tags[<isindex>-&lt;isindex&gt;] tests/test_clean.py::test_escaping_tags[<sarcasm/>-&lt;sarcasm/&gt;] tests/test_clean.py::test_escaping_tags[<sarcasm>-&lt;sarcasm&gt;] tests/test_clean.py::test_escaping_tags[</sarcasm>-&lt;/sarcasm&gt;] tests/test_clean.py::test_escaping_tags[</ tests/test_clean.py::test_escaping_tags[</3-&lt;/3] tests/test_clean.py::test_escaping_tags[<bar@example.com>-&lt;bar@example.com&gt;] tests/test_clean.py::test_escaping_tags[Favorite tests/test_clean.py::test_stripping_tags_is_safe[<scri<script>pt>alert(1)</scr</script>ipt>-pt&gt;alert(1)ipt&gt;] tests/test_clean.py::test_stripping_tags_is_safe[<scri<scri<script>pt>pt>alert(1)</script>-pt&gt;pt&gt;alert(1)] tests/test_clean.py::test_allowed_styles tests/test_clean.py::test_href_with_wrong_tag tests/test_clean.py::test_disallowed_attr tests/test_clean.py::test_unquoted_attr_values_are_quoted tests/test_clean.py::test_unquoted_event_handler_attr_value tests/test_clean.py::test_invalid_filter_attr tests/test_clean.py::test_poster_attribute tests/test_clean.py::test_attributes_callable tests/test_clean.py::test_attributes_wildcard tests/test_clean.py::test_attributes_wildcard_callable tests/test_clean.py::test_attributes_tag_callable tests/test_clean.py::test_attributes_tag_list tests/test_clean.py::test_attributes_list tests/test_clean.py::test_svg_attr_val_allows_ref tests/test_clean.py::test_svg_allow_local_href[<svg><pattern tests/test_clean.py::test_svg_allow_local_href_nonlocal[<svg><pattern tests/test_clean.py::test_invisible_characters[1\x0723-1?23] tests/test_clean.py::test_invisible_characters[1\x0823-1?23] tests/test_clean.py::test_invisible_characters[1\x0b23-1?23] tests/test_clean.py::test_invisible_characters[1\x0c23-1?23] tests/test_clean.py::test_invisible_characters[import tests/test_clean.py::test_nonexistent_namespace tests/test_clean.py::test_regressions[1.test] tests/test_clean.py::test_regressions[2.test] tests/test_clean.py::test_regressions[3.test] tests/test_clean.py::test_regressions[4.test] tests/test_clean.py::test_regressions[5.test] tests/test_clean.py::test_regressions[6.test] tests/test_clean.py::test_regressions[7.test] tests/test_clean.py::test_regressions[8.test] tests/test_clean.py::test_regressions[9.test] tests/test_clean.py::test_regressions[10.test] tests/test_clean.py::test_regressions[11.test] tests/test_clean.py::test_regressions[12.test] tests/test_clean.py::test_regressions[13.test] tests/test_clean.py::test_regressions[14.test] tests/test_clean.py::test_regressions[15.test] tests/test_clean.py::test_regressions[16.test] tests/test_clean.py::test_regressions[17.test] tests/test_clean.py::test_regressions[18.test] tests/test_clean.py::test_regressions[19.test] tests/test_clean.py::test_regressions[20.test] tests/test_clean.py::TestCleaner::test_basics tests/test_clean.py::TestCleaner::test_filters tests/test_linkify.py::test_empty tests/test_linkify.py::test_simple_link tests/test_linkify.py::test_trailing_slash tests/test_linkify.py::test_mangle_link tests/test_linkify.py::test_mangle_text tests/test_linkify.py::test_email_link[a tests/test_linkify.py::test_email_link[aussie tests/test_linkify.py::test_email_link[email tests/test_linkify.py::test_email_link[<br>jinkyun@example.com-True-<br><a tests/test_linkify.py::test_email_link[mailto tests/test_linkify.py::test_email_link["\\\n"@opa.ru-True-"\\\n"@opa.ru] tests/test_linkify.py::test_email_link_escaping["james"@example.com-<a tests/test_linkify.py::test_email_link_escaping["j'ames"@example.com-<a tests/test_linkify.py::test_email_link_escaping["ja>mes"@example.com-<a tests/test_linkify.py::test_prevent_links[callback0-a tests/test_linkify.py::test_prevent_links[callback1-a tests/test_linkify.py::test_prevent_links[callback2-a tests/test_linkify.py::test_prevent_links[callback3-a tests/test_linkify.py::test_prevent_links[callback4-a tests/test_linkify.py::test_prevent_links[callback5-a tests/test_linkify.py::test_set_attrs tests/test_linkify.py::test_only_proto_links tests/test_linkify.py::test_stop_email tests/test_linkify.py::test_tlds[example.com-<a tests/test_linkify.py::test_tlds[example.co-<a tests/test_linkify.py::test_tlds[example.co.uk-<a tests/test_linkify.py::test_tlds[example.edu-<a tests/test_linkify.py::test_tlds[example.xxx-<a tests/test_linkify.py::test_tlds[bit.ly/fun-<a tests/test_linkify.py::test_tlds[example.yyy-example.yyy] tests/test_linkify.py::test_tlds[brie-brie] tests/test_linkify.py::test_escaping tests/test_linkify.py::test_nofollow_off tests/test_linkify.py::test_link_in_html tests/test_linkify.py::test_links_https tests/test_linkify.py::test_add_rel_nofollow tests/test_linkify.py::test_url_with_path tests/test_linkify.py::test_link_ftp tests/test_linkify.py::test_link_query tests/test_linkify.py::test_link_fragment tests/test_linkify.py::test_link_entities tests/test_linkify.py::test_escaped_html tests/test_linkify.py::test_link_http_complete tests/test_linkify.py::test_non_url tests/test_linkify.py::test_javascript_url tests/test_linkify.py::test_unsafe_url tests/test_linkify.py::test_skip_tags tests/test_linkify.py::test_libgl tests/test_linkify.py::test_end_of_sentence[example.com-.] tests/test_linkify.py::test_end_of_sentence[example.com-...] tests/test_linkify.py::test_end_of_sentence[ex.com/foo-.] tests/test_linkify.py::test_end_of_sentence[ex.com/foo-....] tests/test_linkify.py::test_end_of_clause tests/test_linkify.py::test_sarcasm tests/test_linkify.py::test_wrapping_parentheses[(example.com)-expected_data0] tests/test_linkify.py::test_wrapping_parentheses[(example.com/)-expected_data1] tests/test_linkify.py::test_wrapping_parentheses[(example.com/foo)-expected_data2] tests/test_linkify.py::test_wrapping_parentheses[(((example.com/))))-expected_data3] tests/test_linkify.py::test_wrapping_parentheses[example.com/))-expected_data4] tests/test_linkify.py::test_wrapping_parentheses[(foo tests/test_linkify.py::test_wrapping_parentheses[http://en.wikipedia.org/wiki/Test_(assessment)-expected_data7] tests/test_linkify.py::test_wrapping_parentheses[(http://en.wikipedia.org/wiki/Test_(assessment))-expected_data8] tests/test_linkify.py::test_wrapping_parentheses[((http://en.wikipedia.org/wiki/Test_(assessment))-expected_data9] tests/test_linkify.py::test_wrapping_parentheses[(http://en.wikipedia.org/wiki/Test_(assessment)))-expected_data10] tests/test_linkify.py::test_wrapping_parentheses[(http://en.wikipedia.org/wiki/)Test_(assessment-expected_data11] tests/test_linkify.py::test_wrapping_parentheses[hello tests/test_linkify.py::test_parentheses_with_removing tests/test_linkify.py::test_ports[http://foo.com:8000-expected_data0] tests/test_linkify.py::test_ports[http://foo.com:8000/-expected_data1] tests/test_linkify.py::test_ports[http://bar.com:xkcd-expected_data2] tests/test_linkify.py::test_ports[http://foo.com:81/bar-expected_data3] tests/test_linkify.py::test_ports[http://foo.com:-expected_data4] tests/test_linkify.py::test_ports[http://foo.com:\u0663\u0669/-expected_data5] tests/test_linkify.py::test_ports[http://foo.com:\U0001d7e0\U0001d7d8/-expected_data6] tests/test_linkify.py::test_ignore_bad_protocols tests/test_linkify.py::test_link_emails_and_urls tests/test_linkify.py::test_links_case_insensitive tests/test_linkify.py::test_elements_inside_links tests/test_linkify.py::test_drop_link_tags tests/test_linkify.py::test_naughty_unescaping[&lt;br&gt;-&lt;br&gt;] tests/test_linkify.py::test_naughty_unescaping[&lt;br&gt; tests/test_linkify.py::test_hang tests/test_linkify.py::test_hyphen_in_mail tests/test_linkify.py::test_url_re_arg tests/test_linkify.py::test_email_re_arg tests/test_linkify.py::test_linkify_idempotent tests/test_linkify.py::TestLinkify::test_no_href_links tests/test_linkify.py::TestLinkify::test_rel_already_there tests/test_linkify.py::TestLinkify::test_only_text_is_linkified tests/test_linkify.py::test_linkify_filter[abc-abc] tests/test_linkify.py::test_linkify_filter[example.com-<a tests/test_linkify.py::test_linkify_filter[link: