imgaudit : verdict « morte » sur preuve seulement (404/410) — les 403/429 des CDN (rate-limit DuProprio, anti-hotlink) ne retirent plus d images ; commits par tranches (plus de verrou BD long) ; 8 workers
1 changed file +12 −4
modified
immoka/imgaudit.py
+12 −4
@@ -124,13 +124,20 @@ def image_size(data: bytes) -> tuple[int, int] | None: | ||
| 124 | 124 | |
| 125 | 125 | |
| 126 | 126 | def check_url(url: str) -> dict: |
| 127 | − """Vérifie une URL d'image : {ok, status, width, height, bytes, reason}.""" | |
| 127 | + """Vérifie une URL d'image : {ok, status, width, height, bytes, reason}. | |
| 128 | + | |
| 129 | + ⚠ Verdict « morte » UNIQUEMENT sur preuve solide (404/410) : un 403/429 est | |
| 130 | + presque toujours du rate-limiting ou de l'anti-hotlink du CDN (bug payé : | |
| 131 | + ~6 000 galeries DuProprio retirées à tort). En cas de doute on garde | |
| 132 | + l'image — le repli onError du frontend couvre les rares vraies mortes.""" | |
| 128 | 133 | try: |
| 129 | 134 | r = requests.get(url, headers={"User-Agent": UA, "Range": "bytes=0-65535"}, |
| 130 | 135 | timeout=TIMEOUT, stream=True) |
| 131 | 136 | status = r.status_code |
| 132 | − if status >= 400: | |
| 137 | + if status in (404, 410): | |
| 133 | 138 | return {"ok": 0, "status": status, "reason": "http"} |
| 139 | + if status >= 400: | |
| 140 | + return {"ok": 1, "status": status, "reason": "non_verifiable"} | |
| 134 | 141 | data = next(r.iter_content(65536), b"") or b"" |
| 135 | 142 | r.close() |
| 136 | 143 | total = int((r.headers.get("Content-Range") or "/0").split("/")[-1] or 0) \ |
@@ -151,7 +158,8 @@ def check_url(url: str) -> dict: | ||
| 151 | 158 | "bytes": total, "reason": "poids_suspect"} |
| 152 | 159 | return {"ok": 1, "status": status, "width": w, "height": h, "bytes": total} |
| 153 | 160 | except requests.RequestException: |
| 154 | − return {"ok": 0, "status": 0, "reason": "timeout"} | |
| 161 | + # réseau/timeout : non concluant — ne jamais retirer sur un doute | |
| 162 | + return {"ok": 1, "status": 0, "reason": "non_verifiable"} | |
| 155 | 163 | |
| 156 | 164 | |
| 157 | 165 | # --------------------------------------------------------------------------- |
@@ -221,7 +229,7 @@ def audit_listing(con: sqlite3.Connection, uid: str, images: list[str], | ||
| 221 | 229 | return new_images, details, checked |
| 222 | 230 | |
| 223 | 231 | |
| 224 | −def run_batch(limit: int = 2000, workers: int = 24) -> dict: | |
| 232 | +def run_batch(limit: int = 2000, workers: int = 8) -> dict: | |
| 225 | 233 | """Audit réseau budgété : les annonces publiées jamais auditées d'abord. |
| 226 | 234 | |
| 227 | 235 | Appelé après chaque synchronisation (ingest.watch) ; relancer avec un gros |
| 228 | 236 | |