main.py 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  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. if path == '/':
  41. return 'artist'
  42. raise ValueError('unsupported url: "{}"'.format(path))
  43. def main():
  44. args = get_parser().parse_args()
  45. logging.basicConfig(level=args.loglevel)
  46. logging.getLogger('selenium.webdriver').setLevel(logging.WARNING)
  47. logging.getLogger('requests').setLevel(logging.WARNING)
  48. if args.mode is None:
  49. args.mode = get_mode(args.url)
  50. log.info('Going in %s mode' % args.mode)
  51. prefs = {
  52. 'dom.audiochannel.mutedByDefault': True
  53. }
  54. with Browser(args.driver, profile_preferences=prefs) as br:
  55. # get track info
  56. if args.mode == 'track':
  57. tracks = visit_track(br, args.url)
  58. elif args.mode == 'album':
  59. tracks = visit_album(br, args.url)
  60. else:
  61. tracks = visit_artist(br, args.url)
  62. # do something
  63. if args.do == 'print':
  64. for track in tracks:
  65. print(json.dumps(track))
  66. elif args.do == 'wgetprint':
  67. for track in tracks:
  68. cmd = ['wget', '-nv', "'%s'" % track['url'],
  69. '-O', "'%s'" %
  70. join(args.download_base,
  71. '-'.join((track['artist'], track['album'],
  72. track['title']))).replace(' ', '_')
  73. ]
  74. print(' '.join(cmd))
  75. elif args.do == 'download':
  76. pool = multiprocessing.Pool(processes=args.jobs)
  77. for res in pool.imap_unordered(functools.partial(download_track,
  78. args=args),
  79. tracks):
  80. print('R', res)
  81. pool.close()
  82. pool.join()
  83. else:
  84. raise NotImplementedError('action ' + args.do)
  85. if __name__ == '__main__':
  86. main()