Bubbles30 commited on
Commit
ae82fbc
·
verified ·
1 Parent(s): 358a79e

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +89 -40
app.py CHANGED
@@ -35,98 +35,149 @@ USER_AGENTS = [
35
 
36
  fail_lock = threading.Lock()
37
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
38
  def thread_log_failure(failures, msg):
39
  with fail_lock:
40
  failures.append(msg)
41
 
42
- def download_image(url, out_path, code, suf, failures):
43
- import traceback
44
- from selenium.common.exceptions import TimeoutException
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
45
 
46
  def log(msg):
47
  entry = f"{code}{suf}: {msg}"
48
- print(entry)
49
- with fail_lock:
50
- failures.append(entry)
 
 
 
 
 
 
51
 
52
  parsed = urlparse(url)
53
  referer = f"{parsed.scheme}://{parsed.netloc}/"
54
  headers = {
55
  "User-Agent": random.choice(USER_AGENTS),
56
- "Referer": referer,
57
- "Accept": "image/webp,image/apng,image/*,*/*;q=0.8",
58
  }
59
 
60
  log(f"Starting download: {url}")
61
 
62
  # 1) cloudscraper
63
  try:
64
- scraper = cloudscraper.create_scraper(browser={"browser": "chrome", "platform": "windows"})
65
  r = scraper.get(url, headers=headers, stream=True, timeout=30)
66
  r.raise_for_status()
67
- if "image" in r.headers.get("Content-Type", "").lower():
68
  with open(out_path, "wb") as f:
69
  for chunk in r.iter_content(8192):
70
  f.write(chunk)
71
  return True
72
- log(f"Cloudscraper non-image content-type: {r.headers.get('Content-Type')}")
73
  except Exception as e:
74
- log(f"Cloudscraper error: {e}\n{traceback.format_exc()}")
75
 
76
- # 2) requests fallback
77
  try:
78
- r = requests.get(url, headers=headers, stream=True, timeout=60, allow_redirects=True, verify=False)
 
79
  r.raise_for_status()
80
- if "image" in r.headers.get("Content-Type", "").lower():
81
  with open(out_path, "wb") as f:
82
  for chunk in r.iter_content(8192):
83
  f.write(chunk)
84
  return True
85
- log(f"Requests non-image content-type: {r.headers.get('Content-Type')}")
86
  except Exception as e:
87
- log(f"Requests error: {e}\n{traceback.format_exc()}")
88
 
89
- # 3) public proxy fallback
90
  try:
91
  proxy_target = parsed.netloc + parsed.path + (f"?{parsed.query}" if parsed.query else "")
92
- proxy_url = f"https://images.weserv.nl/?url={quote(proxy_target, safe='')}"
93
  r = requests.get(proxy_url, headers=headers, stream=True, timeout=30)
94
  r.raise_for_status()
95
- if "image" in r.headers.get("Content-Type", "").lower():
96
  with open(out_path, "wb") as f:
97
  for chunk in r.iter_content(8192):
98
  f.write(chunk)
99
  return True
100
- log(f"Proxy non-image content-type: {r.headers.get('Content-Type')}")
101
  except Exception as e:
102
- log(f"Proxy error: {e}\n{traceback.format_exc()}")
103
 
104
- # 4) Selenium fallback - improved wait & error handling
105
- driver = None
106
  try:
107
  opts = Options()
108
  opts.add_argument("--headless")
109
  opts.add_argument("--disable-gpu")
110
  opts.add_argument("--no-sandbox")
111
  opts.add_argument(f"user-agent={headers['User-Agent']}")
112
- opts.add_argument("--disable-dev-shm-usage") # fix some Linux errors
113
 
114
- driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()), options=opts)
115
- driver.set_page_load_timeout(30)
 
 
116
  driver.get(url)
 
117
 
118
- wait = WebDriverWait(driver, 20)
119
- img_el = wait.until(EC.presence_of_element_located((By.TAG_NAME, "img")))
120
-
121
- # Execute JS to get image data URL
122
  data_url = driver.execute_script("""
123
  const img = arguments[0];
124
  const c = document.createElement('canvas');
125
- c.width = img.naturalWidth;
126
- c.height = img.naturalHeight;
127
- c.getContext('2d').drawImage(img, 0, 0);
128
  return c.toDataURL('image/png');
129
  """, img_el)
 
130
 
131
  header, b64 = data_url.split(",", 1)
132
  raw = base64.b64decode(b64)
@@ -134,14 +185,12 @@ def download_image(url, out_path, code, suf, failures):
134
  f.write(raw)
135
  return True
136
 
137
- except TimeoutException:
138
- log("Selenium timeout: Image element not found in time.")
139
  except Exception as e:
140
- log(f"Selenium error: {e}\n{traceback.format_exc()}")
141
- finally:
142
- if driver:
143
- driver.quit()
144
 
 
145
  log("Download failed for all methods")
146
  return False
147
 
 
35
 
36
  fail_lock = threading.Lock()
37
 
38
+ def random_headers(referer):
39
+ return {
40
+ "User-Agent": random.choice(USER_AGENTS),
41
+ "Referer": referer,
42
+ "Accept": "image/webp,image/apng,image/*,*/*;q=0.8",
43
+ }
44
+ def count_links(workbook_file):
45
+ if not workbook_file:
46
+ return ""
47
+ try:
48
+ links = read_links_from_workbook(workbook_file.name)
49
+ return f"🔗 Detected {len(links)} image link(s)."
50
+ except Exception as e:
51
+ return f"❌ Error reading workbook: {e}"
52
+
53
  def thread_log_failure(failures, msg):
54
  with fail_lock:
55
  failures.append(msg)
56
 
57
+ def download_direct_image(url, out_path):
58
+ try:
59
+ r = requests.get(url, stream=True, timeout=30)
60
+ r.raise_for_status()
61
+ if "image" in r.headers.get("Content-Type", "").lower():
62
+ with open(out_path, "wb") as f:
63
+ for chunk in r.iter_content(8192):
64
+ f.write(chunk)
65
+ return True
66
+ return False
67
+ except Exception as e:
68
+ print(f"Direct download failed: {e}")
69
+ return False
70
+
71
+
72
+ from io import BytesIO
73
+ from PIL import Image
74
+
75
+ def download_image(url, out_path, fail_log, code, suf):
76
+ """
77
+ Tries multiple methods to download an image, logs failures with ItemCode names.
78
+ Order:
79
+ 1) cloudscraper
80
+ 2) requests
81
+ 3) public proxy (weserv)
82
+ 4) Selenium canvas fallback
83
+ Returns True on success, False on all failures.
84
+ """
85
+ import requests, cloudscraper, random, time, base64, os
86
+ from urllib.parse import urlparse, quote
87
+ from selenium import webdriver
88
+ from selenium.webdriver.chrome.options import Options
89
+ from selenium.webdriver.chrome.service import Service
90
+ from webdriver_manager.chrome import ChromeDriverManager
91
 
92
  def log(msg):
93
  entry = f"{code}{suf}: {msg}"
94
+ with open(fail_log, "a") as f:
95
+ f.write(entry + "\n")
96
+
97
+ USER_AGENTS = [
98
+ "Mozilla/5.0 (Windows NT 10.0; Win64; x64)",
99
+ "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)",
100
+ "Mozilla/5.0 (Linux; Android 10)",
101
+ "Mozilla/5.0 (iPhone; CPU iPhone OS 14_6 like Mac OS X)",
102
+ ]
103
 
104
  parsed = urlparse(url)
105
  referer = f"{parsed.scheme}://{parsed.netloc}/"
106
  headers = {
107
  "User-Agent": random.choice(USER_AGENTS),
108
+ "Referer": referer,
109
+ "Accept": "image/webp,image/apng,image/*,*/*;q=0.8",
110
  }
111
 
112
  log(f"Starting download: {url}")
113
 
114
  # 1) cloudscraper
115
  try:
116
+ scraper = cloudscraper.create_scraper(browser={"browser":"chrome","platform":"windows"})
117
  r = scraper.get(url, headers=headers, stream=True, timeout=30)
118
  r.raise_for_status()
119
+ if "image" in r.headers.get("Content-Type","").lower():
120
  with open(out_path, "wb") as f:
121
  for chunk in r.iter_content(8192):
122
  f.write(chunk)
123
  return True
124
+ log(f"Cloudscraper non-image: {r.headers.get('Content-Type')}")
125
  except Exception as e:
126
+ log(f"Cloudscraper error: {e}")
127
 
128
+ # 2) requests
129
  try:
130
+ r = requests.get(url, headers=headers, stream=True,
131
+ timeout=60, allow_redirects=True, verify=False)
132
  r.raise_for_status()
133
+ if "image" in r.headers.get("Content-Type","").lower():
134
  with open(out_path, "wb") as f:
135
  for chunk in r.iter_content(8192):
136
  f.write(chunk)
137
  return True
138
+ log(f"Requests non-image: {r.headers.get('Content-Type')}")
139
  except Exception as e:
140
+ log(f"Requests error: {e}")
141
 
142
+ # 3) public proxy
143
  try:
144
  proxy_target = parsed.netloc + parsed.path + (f"?{parsed.query}" if parsed.query else "")
145
+ proxy_url = f"https://images.weserv.nl/?url={quote(proxy_target, safe='')}"
146
  r = requests.get(proxy_url, headers=headers, stream=True, timeout=30)
147
  r.raise_for_status()
148
+ if "image" in r.headers.get("Content-Type","").lower():
149
  with open(out_path, "wb") as f:
150
  for chunk in r.iter_content(8192):
151
  f.write(chunk)
152
  return True
153
+ log(f"Proxy non-image: {r.headers.get('Content-Type')}")
154
  except Exception as e:
155
+ log(f"Proxy error: {e}")
156
 
157
+ # 4) Selenium canvas fallback
 
158
  try:
159
  opts = Options()
160
  opts.add_argument("--headless")
161
  opts.add_argument("--disable-gpu")
162
  opts.add_argument("--no-sandbox")
163
  opts.add_argument(f"user-agent={headers['User-Agent']}")
 
164
 
165
+ driver = webdriver.Chrome(
166
+ service=Service(ChromeDriverManager().install()),
167
+ options=opts
168
+ )
169
  driver.get(url)
170
+ time.sleep(5) # allow JS & image to load
171
 
172
+ img_el = driver.find_element("tag name", "img")
 
 
 
173
  data_url = driver.execute_script("""
174
  const img = arguments[0];
175
  const c = document.createElement('canvas');
176
+ c.width = img.naturalWidth; c.height = img.naturalHeight;
177
+ c.getContext('2d').drawImage(img,0,0);
 
178
  return c.toDataURL('image/png');
179
  """, img_el)
180
+ driver.quit()
181
 
182
  header, b64 = data_url.split(",", 1)
183
  raw = base64.b64decode(b64)
 
185
  f.write(raw)
186
  return True
187
 
 
 
188
  except Exception as e:
189
+ try: driver.quit()
190
+ except: pass
191
+ log(f"Selenium error: {e}")
 
192
 
193
+ # All methods failed
194
  log("Download failed for all methods")
195
  return False
196