Spaces:
Paused
Paused
Update app.py
Browse files
app.py
CHANGED
|
@@ -42,47 +42,68 @@ def log_failure(path, reason):
|
|
| 42 |
with open(path, "a") as f:
|
| 43 |
f.write(reason + "\n")
|
| 44 |
|
| 45 |
-
|
| 46 |
-
|
| 47 |
-
from urllib.parse import urlparse
|
| 48 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 49 |
def log(msg):
|
| 50 |
with open(fail_log, "a") as f:
|
| 51 |
-
f.write(f"{code}{suf}: {msg}\n")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 52 |
|
| 53 |
headers = {
|
| 54 |
"User-Agent": random.choice(USER_AGENTS),
|
| 55 |
-
"Referer":
|
| 56 |
}
|
| 57 |
|
| 58 |
-
#
|
| 59 |
try:
|
| 60 |
-
r = requests.get(
|
|
|
|
|
|
|
| 61 |
r.raise_for_status()
|
| 62 |
-
|
|
|
|
| 63 |
with open(out_path, "wb") as f:
|
| 64 |
-
for chunk in r.iter_content(
|
| 65 |
f.write(chunk)
|
| 66 |
return True
|
| 67 |
-
log(f"requests non-image: {
|
| 68 |
except Exception as e:
|
| 69 |
log(f"requests error: {e}")
|
| 70 |
|
| 71 |
-
#
|
| 72 |
try:
|
| 73 |
-
scr = cloudscraper.create_scraper(
|
| 74 |
-
|
|
|
|
|
|
|
|
|
|
| 75 |
r.raise_for_status()
|
| 76 |
-
|
|
|
|
| 77 |
with open(out_path, "wb") as f:
|
| 78 |
-
for chunk in r.iter_content(
|
| 79 |
f.write(chunk)
|
| 80 |
return True
|
| 81 |
-
log(f"cloudscraper non-image: {
|
| 82 |
except Exception as e:
|
| 83 |
log(f"cloudscraper error: {e}")
|
| 84 |
|
| 85 |
-
|
|
|
|
| 86 |
return False
|
| 87 |
|
| 88 |
|
|
@@ -297,12 +318,16 @@ def handle_batch(workbook_path, fmt, w, h):
|
|
| 297 |
|
| 298 |
# Download with tracking
|
| 299 |
futures = {}
|
| 300 |
-
with ThreadPoolExecutor(max_workers=
|
|
|
|
| 301 |
for code, url, dl_path, suf in tasks:
|
| 302 |
-
|
| 303 |
-
|
|
|
|
| 304 |
for fut in as_completed(futures):
|
| 305 |
success = fut.result()
|
|
|
|
|
|
|
| 306 |
code, suf = futures[fut]
|
| 307 |
if not success:
|
| 308 |
log_failure(fail_log, f"{code}{suf}: download failed")
|
|
|
|
| 42 |
with open(path, "a") as f:
|
| 43 |
f.write(reason + "\n")
|
| 44 |
|
| 45 |
+
import requests, cloudscraper
|
| 46 |
+
from urllib.parse import quote, urlparse
|
|
|
|
| 47 |
|
| 48 |
+
def download_image_fast(url, out_path, fail_log, code, suf):
|
| 49 |
+
"""
|
| 50 |
+
1) Encode the URL for safe HTTP requests
|
| 51 |
+
2) Try a short requests.get
|
| 52 |
+
3) If that fails, try a short cloudscraper.get
|
| 53 |
+
4) Log *every* status/exception so nothing is silent
|
| 54 |
+
"""
|
| 55 |
def log(msg):
|
| 56 |
with open(fail_log, "a") as f:
|
| 57 |
+
f.write(f"{code}{suf}: {msg}\\n")
|
| 58 |
+
|
| 59 |
+
# 1) URL‑encode (spaces, parens, etc.)
|
| 60 |
+
# Keep scheme and netloc intact, encode path+query
|
| 61 |
+
parts = urlparse(url)
|
| 62 |
+
safe_path = quote(parts.path + ("?"+parts.query if parts.query else ""),
|
| 63 |
+
safe="/?=&%")
|
| 64 |
+
safe_url = f"{parts.scheme}://{parts.netloc}{safe_path}"
|
| 65 |
|
| 66 |
headers = {
|
| 67 |
"User-Agent": random.choice(USER_AGENTS),
|
| 68 |
+
"Referer": parts.netloc,
|
| 69 |
}
|
| 70 |
|
| 71 |
+
# 2) Try plain requests
|
| 72 |
try:
|
| 73 |
+
r = requests.get(safe_url, headers=headers,
|
| 74 |
+
timeout=8, stream=True, allow_redirects=True)
|
| 75 |
+
log(f"requests status={r.status_code}")
|
| 76 |
r.raise_for_status()
|
| 77 |
+
ct = r.headers.get("Content-Type","")
|
| 78 |
+
if "image" in ct.lower():
|
| 79 |
with open(out_path, "wb") as f:
|
| 80 |
+
for chunk in r.iter_content(16384):
|
| 81 |
f.write(chunk)
|
| 82 |
return True
|
| 83 |
+
log(f"requests non-image: {ct}")
|
| 84 |
except Exception as e:
|
| 85 |
log(f"requests error: {e}")
|
| 86 |
|
| 87 |
+
# 3) cloudscraper fallback
|
| 88 |
try:
|
| 89 |
+
scr = cloudscraper.create_scraper(
|
| 90 |
+
browser={"browser":"chrome","platform":"windows"})
|
| 91 |
+
r = scr.get(safe_url, headers=headers,
|
| 92 |
+
timeout=8, stream=True, allow_redirects=True)
|
| 93 |
+
log(f"cloudscraper status={r.status_code}")
|
| 94 |
r.raise_for_status()
|
| 95 |
+
ct = r.headers.get("Content-Type","")
|
| 96 |
+
if "image" in ct.lower():
|
| 97 |
with open(out_path, "wb") as f:
|
| 98 |
+
for chunk in r.iter_content(16384):
|
| 99 |
f.write(chunk)
|
| 100 |
return True
|
| 101 |
+
log(f"cloudscraper non-image: {ct}")
|
| 102 |
except Exception as e:
|
| 103 |
log(f"cloudscraper error: {e}")
|
| 104 |
|
| 105 |
+
# 4) All failed
|
| 106 |
+
log("download failed for all methods")
|
| 107 |
return False
|
| 108 |
|
| 109 |
|
|
|
|
| 318 |
|
| 319 |
# Download with tracking
|
| 320 |
futures = {}
|
| 321 |
+
with ThreadPoolExecutor(max_workers=min(32, CPU_CORES*2)) as ex:
|
| 322 |
+
futures = []
|
| 323 |
for code, url, dl_path, suf in tasks:
|
| 324 |
+
futures.append(ex.submit(
|
| 325 |
+
download_image_fast, url, dl_path, fail_log, code, suf
|
| 326 |
+
))
|
| 327 |
for fut in as_completed(futures):
|
| 328 |
success = fut.result()
|
| 329 |
+
# failures logged inside download_image_fast already
|
| 330 |
+
|
| 331 |
code, suf = futures[fut]
|
| 332 |
if not success:
|
| 333 |
log_failure(fail_log, f"{code}{suf}: download failed")
|