更新支持pg下载多版本歌曲
Showing
4 changed files
with
122 additions
and
0 deletions
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
scripts/download_cos.py
0 → 100755
| 1 | #!/usr/bin/env python3 | ||
| 2 | import argparse | ||
| 3 | import csv | ||
| 4 | import os | ||
| 5 | import re | ||
| 6 | import sys | ||
| 7 | from pathlib import Path | ||
| 8 | from urllib.parse import urlparse | ||
| 9 | |||
| 10 | from dotenv import load_dotenv | ||
| 11 | from qcloud_cos import CosConfig, CosS3Client | ||
| 12 | |||
| 13 | load_dotenv(Path(__file__).resolve().parents[1] / '.env') | ||
| 14 | |||
| 15 | AUDIO_EXTS = {'.mp3', '.wav', '.flac', '.m4a', '.aac', '.ogg', '.wma', '.ape', '.alac'} | ||
| 16 | |||
| 17 | |||
| 18 | def normalize_key(raw_url: str) -> str: | ||
| 19 | if not raw_url: | ||
| 20 | return '' | ||
| 21 | raw_url = raw_url.strip() | ||
| 22 | if re.match(r'^https?://', raw_url, re.I): | ||
| 23 | return urlparse(raw_url).path.lstrip('/') | ||
| 24 | return raw_url.lstrip('/') | ||
| 25 | |||
| 26 | |||
| 27 | def ext_ok(path: str) -> bool: | ||
| 28 | return Path(path).suffix.lower() in AUDIO_EXTS | ||
| 29 | |||
| 30 | |||
| 31 | def main(): | ||
| 32 | ap = argparse.ArgumentParser() | ||
| 33 | ap.add_argument('--manifest', default='output_selection_budgeted/selected_files.csv') | ||
| 34 | ap.add_argument('--output-dir', default='downloads') | ||
| 35 | ap.add_argument('--types', default='1,7,8,11,16') | ||
| 36 | ap.add_argument('--song-limit', type=int, default=3) | ||
| 37 | ap.add_argument('--start-song-offset', type=int, default=0) | ||
| 38 | ap.add_argument('--overwrite', action='store_true') | ||
| 39 | ap.add_argument('--fail-log', default='download_failures.csv') | ||
| 40 | args = ap.parse_args() | ||
| 41 | |||
| 42 | region = os.environ['COS_REGION'] | ||
| 43 | secret_id = os.environ['COS_SECRET_ID'] | ||
| 44 | secret_key = os.environ['COS_SECRET_KEY'] | ||
| 45 | bucket = os.environ['COS_BUCKET'] | ||
| 46 | |||
| 47 | config = CosConfig(Region=region, SecretId=secret_id, SecretKey=secret_key) | ||
| 48 | client = CosS3Client(config) | ||
| 49 | wanted_types = {int(x) for x in args.types.split(',') if x.strip()} | ||
| 50 | |||
| 51 | out_dir = Path(args.output_dir) | ||
| 52 | out_dir.mkdir(parents=True, exist_ok=True) | ||
| 53 | fail_log = Path(args.fail_log) | ||
| 54 | fail_exists = fail_log.exists() | ||
| 55 | fail_f = fail_log.open('a', encoding='utf-8', newline='') | ||
| 56 | fail_w = csv.writer(fail_f) | ||
| 57 | if not fail_exists: | ||
| 58 | fail_w.writerow(['song_id', 'type', 'url', 'error']) | ||
| 59 | |||
| 60 | downloaded = skipped = errors = 0 | ||
| 61 | active_song_ids = [] | ||
| 62 | current_song = None | ||
| 63 | started = False | ||
| 64 | song_counter = 0 | ||
| 65 | |||
| 66 | with open(args.manifest, 'r', encoding='utf-8', newline='') as f: | ||
| 67 | reader = csv.DictReader(f) | ||
| 68 | for row in reader: | ||
| 69 | sid = row['song_id'] | ||
| 70 | if sid != current_song: | ||
| 71 | current_song = sid | ||
| 72 | if song_counter < args.start_song_offset: | ||
| 73 | song_counter += 1 | ||
| 74 | continue | ||
| 75 | if args.song_limit and started and len(active_song_ids) >= args.song_limit and sid not in set(active_song_ids): | ||
| 76 | break | ||
| 77 | if sid not in active_song_ids: | ||
| 78 | active_song_ids.append(sid) | ||
| 79 | started = True | ||
| 80 | if sid not in active_song_ids: | ||
| 81 | continue | ||
| 82 | try: | ||
| 83 | t = int(row['type']) | ||
| 84 | except Exception: | ||
| 85 | skipped += 1 | ||
| 86 | continue | ||
| 87 | if t not in wanted_types: | ||
| 88 | skipped += 1 | ||
| 89 | continue | ||
| 90 | key = normalize_key(row['url']) | ||
| 91 | if not key or not ext_ok(key): | ||
| 92 | skipped += 1 | ||
| 93 | continue | ||
| 94 | target_dir = out_dir / sid / f'type_{t}' | ||
| 95 | target_dir.mkdir(parents=True, exist_ok=True) | ||
| 96 | target = target_dir / Path(key).name | ||
| 97 | if target.exists() and not args.overwrite: | ||
| 98 | skipped += 1 | ||
| 99 | continue | ||
| 100 | try: | ||
| 101 | client.download_file(Bucket=bucket, Key=key, DestFilePath=str(target)) | ||
| 102 | downloaded += 1 | ||
| 103 | if downloaded % 50 == 0: | ||
| 104 | print({'downloaded': downloaded, 'songs': len(active_song_ids), 'last': str(target)}) | ||
| 105 | except Exception as e: | ||
| 106 | errors += 1 | ||
| 107 | fail_w.writerow([sid, t, row['url'], str(e)]) | ||
| 108 | fail_f.flush() | ||
| 109 | print({'error_song': sid, 'type': t, 'key': key, 'error': str(e)}, file=sys.stderr) | ||
| 110 | |||
| 111 | fail_f.close() | ||
| 112 | print({ | ||
| 113 | 'downloaded_files': downloaded, | ||
| 114 | 'skipped_rows': skipped, | ||
| 115 | 'error_files': errors, | ||
| 116 | 'song_count': len(active_song_ids), | ||
| 117 | 'output_dir': str(out_dir.resolve()), | ||
| 118 | }) | ||
| 119 | |||
| 120 | |||
| 121 | if __name__ == '__main__': | ||
| 122 | main() |
scripts/download_from_db.py
0 → 100755
This diff is collapsed.
Click to expand it.
-
Please register or sign in to post a comment