main.py 3.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. from os.path import join
  2. import argparse
  3. from urllib.parse import urlparse
  4. import logging
  5. import json
  6. import multiprocessing
  7. import functools
  8. from splinter import Browser
  9. from .download import download_track
  10. from .visit import visit_track, visit_album, visit_artist
  11. log = logging.getLogger(__name__)
  12. def get_parser():
  13. p = argparse.ArgumentParser(
  14. description='Download tracks from bandcamp, sharing is caring!',
  15. formatter_class=argparse.ArgumentDefaultsHelpFormatter)
  16. p.add_argument('url')
  17. p.add_argument('--loglevel', default='INFO', help='Log level',
  18. choices=['DEBUG', 'INFO', 'WARNING', 'ERROR'])
  19. info = p.add_argument_group('fetch track info')
  20. info.add_argument('--driver', default='firefox',
  21. help='Internal splinter option',
  22. choices=['firefox', 'chrome'])
  23. info.add_argument('--mode', default=None,
  24. choices=['album', 'track', 'artist'])
  25. do = p.add_argument_group('what to do with fetched urls')
  26. do.add_argument('--do', default='print',
  27. help='What to do with retrieved informations',
  28. choices=['print', 'wgetprint', 'download'])
  29. do.add_argument('--download-base', default='.',
  30. help='Only applies to wget')
  31. do.add_argument('-j', '--jobs', default=3, type=int,
  32. help='Parallel downloads')
  33. return p
  34. def get_mode(url):
  35. path = urlparse(url).path
  36. if path.startswith('/track/'):
  37. return 'track'
  38. if path.startswith('/album/'):
  39. return 'album'
  40. raise ValueError('unsupported url: "{}"'.format(path))
  41. def main():
  42. args = get_parser().parse_args()
  43. logging.basicConfig(level=args.loglevel)
  44. logging.getLogger('selenium.webdriver').setLevel(logging.WARNING)
  45. logging.getLogger('requests').setLevel(logging.WARNING)
  46. if args.mode is None:
  47. args.mode = get_mode(args.url)
  48. log.info('Going in %s mode' % args.mode)
  49. prefs = {
  50. 'dom.audiochannel.mutedByDefault': True
  51. }
  52. with Browser(args.driver, profile_preferences=prefs) as br:
  53. # get track info
  54. if args.mode == 'track':
  55. tracks = visit_track(br, args.url)
  56. elif args.mode == 'album':
  57. tracks = visit_album(br, args.url)
  58. else:
  59. tracks = visit_artist(br, args.url)
  60. # do something
  61. if args.do == 'print':
  62. for track in tracks:
  63. print(json.dumps(track))
  64. elif args.do == 'wgetprint':
  65. for track in tracks:
  66. cmd = ['wget', '-nv', "'%s'" % track['url'],
  67. '-O', "'%s'" %
  68. join(args.download_base,
  69. '-'.join((track['artist'], track['album'],
  70. track['title']))).replace(' ', '_')
  71. ]
  72. print(' '.join(cmd))
  73. elif args.do == 'download':
  74. pool = multiprocessing.Pool(processes=args.jobs)
  75. for res in pool.imap_unordered(functools.partial(download_track,
  76. args=args),
  77. tracks):
  78. print('R', res)
  79. pool.close()
  80. pool.join()
  81. else:
  82. raise NotImplementedError('action ' + args.do)
  83. if __name__ == '__main__':
  84. main()