zeit-dl/zeit-dl

94 lines
3.6 KiB
Python
Executable file

#!/usr/bin/env python
import os
import re
from datetime import datetime
import argparse
from playwright.sync_api import sync_playwright
EPAPER = 'https://epaper.zeit.de'
MEINE = 'https://meine.zeit.de'
def main():
parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)
parser.add_argument('user', type=str, help='Username')
parser.add_argument('pwd', type=str, help='Password')
parser.add_argument('-o', '--out', type=str, default=os.getcwd(), help='Output directory')
parser.add_argument('-a', '--abo', type=str, choices=['diezeit', 'zeitcampus', 'zeit-audio'], default='diezeit', help='Subscription (part after abo/)')
parser.add_argument('-i', '--issue', type=str, help='Issue (mostly DD.MM.YYYY)')
parser.add_argument('-t', '--type', type=str, choices=['pdf', 'epub', 'mp3'], default='pdf', help='File type')
parser.add_argument('-f', '--force', action='store_true', help='Redownload file even if already present')
parser.add_argument('--format', type=str, default="{abo}_{issue}.{ext}", help='Filename format. Possible formatting strings are {abo}, {issue}, {ext} and datetime format codes.')
args = parser.parse_args()
if args.user is None or args.pwd is None:
parser.error('You need to supply a username and password')
with sync_playwright() as p:
browser = p.chromium.launch()
page = browser.new_page()
page.goto(MEINE+'/anmelden')
page.locator("input[id='login_email']").fill(args.user)
page.locator("input[id='login_pass']").fill(args.pwd)
try:
page.locator("input[type='submit']").click()
if page.url == MEINE+'/anmelden':
print('could not login')
else:
download(page, args)
except Exception as e:
page.goto(MEINE+'/abmelden')
print(e)
finally:
page.goto(MEINE+'/abmelden')
print('finally: logout')
browser.close()
def download(page, args):
if args.abo == 'zeit-audio':
print('not yet implemented')
else:
if args.issue is None:
page.goto(EPAPER+'/abo/'+args.abo)
page.locator("div.epaper-highlighted > a.btn").click(force=True)
issue = page.url.split('/')[-1]
else:
page.goto(EPAPER+'/abo/'+args.abo+'/'+args.issue)
issue = args.issue
try:
published = datetime.strptime(issue, '%d.%m.%Y')
except ValueError:
published = None
filename = args.format.format(abo=args.abo, issue=issue, ext=args.type)
if published is not None:
filename = published.strftime(filename)
filepath = os.path.join(args.out, filename)
if os.path.isfile(filepath):
print('Issue already exists:', filepath)
return 1
dl_btns = page.locator("div.download-buttons > a.btn").all()
url = None
for btn in dl_btns:
js_obj = btn.get_attribute('data-wt-click')
match = re.search(r"9: ?'([^']*)'", js_obj)
if match.group(1) == args.type:
print(js_obj)
url = EPAPER+btn.get_attribute('href')
continue
if url is None:
print('Could not find appropriate button for', args.type)
return 1
file = page.context.request.get(url)
if file.headers['content-type'] != 'text/html':
print('Downloading {}...'.format(filename))
with open(filepath, 'wb') as f:
f.write(file.body())
if __name__ == "__main__":
main()