ELO scraper: discover the embed link and retry transient failures
Read the current OneDrive link from the stat-check.com/elo iframe on each run, falling back to EMBED_URL if the page can't be read or its link 404s. Retry 429/5xx and network errors up to three times with backoff, after a one-off 503 from the Badger token endpoint failed a run. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -4,8 +4,10 @@ import html
|
||||
import json
|
||||
import re
|
||||
import sys
|
||||
import time
|
||||
import zipfile
|
||||
from pathlib import Path
|
||||
from urllib.error import HTTPError, URLError
|
||||
from urllib.request import Request, urlopen
|
||||
from xml.etree.ElementTree import iterparse
|
||||
|
||||
@@ -16,6 +18,27 @@ NS = {
|
||||
"pkgrel": "http://schemas.openxmlformats.org/package/2006/relationships",
|
||||
}
|
||||
|
||||
# Seconds to wait before each retry of a transient failure.
|
||||
RETRY_DELAYS = (5, 15, 45)
|
||||
|
||||
|
||||
def fetch(req: Request) -> bytes:
|
||||
"""Read a URL, retrying 429/5xx responses and network errors."""
|
||||
for attempt, delay in enumerate((*RETRY_DELAYS, None), start=1):
|
||||
try:
|
||||
with urlopen(req, timeout=60) as resp:
|
||||
return resp.read()
|
||||
except HTTPError as e:
|
||||
if delay is None or not (e.code == 429 or e.code >= 500):
|
||||
raise
|
||||
reason = f"HTTP {e.code}"
|
||||
except (URLError, TimeoutError, ConnectionError) as e:
|
||||
if delay is None:
|
||||
raise
|
||||
reason = str(e)
|
||||
print(f" {req.full_url.split('?')[0]}: {reason}; retry {attempt} in {delay}s", file=sys.stderr)
|
||||
time.sleep(delay)
|
||||
|
||||
|
||||
def metadata_download_url(capture_path: Path) -> str:
|
||||
capture = json.loads(capture_path.read_text())
|
||||
@@ -29,8 +52,7 @@ def metadata_download_url(capture_path: Path) -> str:
|
||||
|
||||
def download(url: str, output: Path) -> None:
|
||||
req = Request(url, headers={"User-Agent": "Mozilla/5.0"})
|
||||
with urlopen(req, timeout=60) as resp:
|
||||
output.write_bytes(resp.read())
|
||||
output.write_bytes(fetch(req))
|
||||
|
||||
|
||||
def shared_strings(zf: zipfile.ZipFile) -> list[str]:
|
||||
|
||||
Reference in New Issue
Block a user