Skip to content

Commit

Permalink
Extract secured playlist directly from the player.
Browse files Browse the repository at this point in the history
  • Loading branch information
danilkister committed Aug 31, 2018
1 parent 3c206c1 commit d69be73
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 25 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ git clone https://github.com/deathtracktor/audioknigi-club-downloader-app.git sr
```
scripts\pip install -r src\requirements.txt
```

* Download [Geckodriver](https://github.com/mozilla/geckodriver/releases), extract to your current working directory.
* Make sure you have the recent version of Firefox installed.
* Run the app:
```
cd src
Expand Down
75 changes: 55 additions & 20 deletions app.py
Original file line number Diff line number Diff line change
@@ -1,51 +1,86 @@
"""
Download complete audio books from audioknigi.ru
"""
import contextlib
import json
import re
import requests
import sys
from bs4 import BeautifulSoup

import requests
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC


CHAPTERS_URL = 'https://audioknigi.club/rest/bid/{}'
USAGE_HELP = '''
Audioknigi.club book downloader.
Usage: {0} <url>
url: a URL of a multi-part audio book.
'''

def get_book_id(url):
"""Get internal book ID."""
resp = requests.get(url)
soup = BeautifulSoup(resp.content, 'html.parser')
AJAX_ON_SUCCESS = '''
$(document).ajaxSuccess(function(event, xhr, opt) {
if (opt.url.indexOf('ajax/bid') !== -1) {
$('body').html($('<div />', {
id: 'playlist',
text: JSON.parse(xhr.responseText).aItems
}))
}
});
'''

INIT_PLAYER = '$(document).audioPlayer({}, 0)'


@contextlib.contextmanager
def open_browser(url):
"""Open a web page with Selenium."""
if getattr(sys, 'frozen', False):
tmp_path = getattr(sys, '_MEIPASS')
os.environ['PATH'] += os.pathsep + tmp_path
browser = webdriver.Firefox()
browser.get(url)
yield browser
browser.close()


def get_book_id(html):
"""Get the internal book ID."""
player = re.compile(r'audioPlayer\((.*)\,')
script_code = next(filter(lambda el: player.search(el.text), soup.findAll('script')))
return player.search(str(script_code)).group(1)
return player.search(html).group(1)



def get_chapters(book_id):
"""Get chapter info."""
for chapter in requests.get(CHAPTERS_URL.format(book_id)).json():
yield chapter['title'], chapter['mp3']
def get_playist(browser, book_id):
"""Extract the playlist."""
browser.execute_script(AJAX_ON_SUCCESS)
browser.execute_script(INIT_PLAYER.format(book_id))
playlist_loaded = EC.presence_of_element_located((By.ID, 'playlist'))
element = WebDriverWait(browser, 60).until(playlist_loaded)
return tuple((track['mp3'], track['title']) for track in json.loads(element.text))


def download_chapter(url):
"""Download a chapter."""
return requests.get(url).content


# start the app
if __name__ == '__main__':

if len(sys.argv) != 2:
print(USAGE_HELP.format(*sys.argv))
sys.exit(1)

book_url = sys.argv[1]

for fname, url in get_chapters(get_book_id(book_url)):
print('Downloading chapter {}'.format(fname))

with open_browser(book_url) as browser:
book_id = get_book_id(browser.page_source)
playlist = get_playist(browser, book_id)

for url, fname in playlist:
print('Downloading chapter "{}"'.format(fname))
with open('{}.mp3'.format(fname), 'wb') as outfile:
outfile.write(download_chapter(url))

print('All done.')

print('All done.')
4 changes: 2 additions & 2 deletions app.spec
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ block_cipher = None


a = Analysis(['app.py'],
pathex=['C:\\Users\\danila\\OneDrive\\downloader\\src'],
binaries=[],
pathex=['.'],
binaries=[('geckodriver.exe', '.')],
datas=[],
hiddenimports=[],
hookspath=[],
Expand Down
Binary file modified dist/app.exe
Binary file not shown.
4 changes: 2 additions & 2 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
bs4==0.0.1
requests==2.18.4
PyInstaller==3.3
PyInstaller==3.3
selenium==3.14.0

0 comments on commit d69be73

Please sign in to comment.