diff --git a/test/test_utils.py b/test/test_utils.py
index 659c6ece53d..b4974d9f4cc 100644
--- a/test/test_utils.py
+++ b/test/test_utils.py
@@ -20,6 +20,7 @@
args_to_str,
encode_base_n,
clean_html,
+ clean_html_markdown,
date_from_str,
DateRange,
detect_exe_version,
@@ -1025,6 +1026,33 @@ def test_clean_html(self):
self.assertEqual(clean_html('a:\n "b"'), 'a: "b"')
self.assertEqual(clean_html('a
\xa0b'), 'a\nb')
+ def test_clean_html_markdown(self):
+ self.assertEqual(clean_html_markdown(
+ '
Happy Text
\n'
+ '
When you do it your way you can go anywhere you choose. And just raise cain. I thought today we would make a happy little stream that\'s just running through the woods here. I was blessed with a very steady hand; and it comes in very handy when you\'re doing these little delicate things. You have to allow the paint to break to make it beautiful. Let\'s do it again then, what the heck.
\n'
+ '
This is your creation - and it\'s just as unique and special as you are.
\n'
+ '
Paint anything you want on the canvas. Create your own world. By now you should be quite happy about what\'s happening here. You can\'t have light without dark. You can\'t know happiness unless you\'ve known sorrow. Let\'s get crazy.
\n'
+ '
\n'
+ '- You can spend all day playing with mountains.
\n'
+ '- We\'ll put a happy little sky in here.
\n'
+ '
\n'
+ '
I like to beat the brush. There we go.
\n'
+ 'We don\'t need any guidelines or formats. All we need to do is just let it flow right out of us. Trees live in your fan brush, but you have to scare them out.
\n'
+ '
'),
+ "# Happy Text\n"
+ "\n"
+ "When you do it your way you can go *anywhere* you choose. And just raise cain. I thought today we would make a happy little stream that's just running through the woods here. I was **blessed** with a very steady hand; and it comes in very handy when you're doing these little delicate things. You have to allow the paint to break to ***make it beautiful***. Let's do it again then, what the heck.\n"
+ "\n"
+ "## This is your creation - and it's just as unique and special as you are.\n"
+ "\n"
+ "Paint **anything** you want on the canvas. Create your own world. By now you should be quite happy about what's happening here. You can't have light without dark. You can't know *happiness* unless you've known *sorrow*. Let's get crazy.\n"
+ "\n"
+ "- You can spend all day playing with mountains. \n"
+ "- We'll put a happy little sky in here. \n"
+ "\n"
+ "I like to beat the brush. There we go. \n"
+ "We don't need any guidelines or formats. All we need to do is just let it flow right out of us. Trees live in your fan brush, but you have to scare them out.")
+
def test_intlist_to_bytes(self):
self.assertEqual(
intlist_to_bytes([0, 1, 127, 128, 255]),
diff --git a/youtube_dl/extractor/audible.py b/youtube_dl/extractor/audible.py
new file mode 100644
index 00000000000..afb168a9bb0
--- /dev/null
+++ b/youtube_dl/extractor/audible.py
@@ -0,0 +1,317 @@
+# coding: utf-8
+from __future__ import unicode_literals
+
+import re
+
+from .common import InfoExtractor
+from ..compat import (
+ compat_urllib_parse_urlencode,
+ compat_urlparse,
+)
+from ..utils import (
+ clean_html,
+ clean_html_markdown,
+ ExtractorError,
+ extract_attributes,
+ get_element_by_class,
+ get_element_by_id,
+ get_elements_by_class,
+ unified_strdate,
+ urlencode_postdata,
+)
+
+
+class AudibleBaseIE(InfoExtractor):
+ _BASE_URL = 'https://www.audible.com'
+
+ def _is_logged_in(self, html=None):
+ if not html:
+ html = self._download_webpage(
+ self._BASE_URL, None,
+ 'Checking login status')
+
+ logged_in_elm = get_element_by_class('ui-it-credit-balance', html)
+
+ if logged_in_elm is None:
+ self.report_warning(
+ 'You don\'t appear to be logged in. You will not be able to '
+ 'download full audiobooks without being logged in. It is '
+ 'currently not possible to automate the login process for '
+ 'Audible. You must login via a browser, then export your '
+ 'cookies and pass the cookie file to youtube-dl with '
+ '--cookies.')
+ return False
+
+ else:
+ return True
+
+
+class AudibleIE(AudibleBaseIE):
+ IE_NAME = 'audible'
+ _VALID_URL = r'https?://(?:.+?\.)?audible\.com/pd/(?:.+)/(?P