Download tools/target.py from 1990two/XTOOLS: direct link, hf CLI and curl.
- Browser
- Download file 1.48 kB
-
https://huggingface.co/spaces/1990two/XTOOLS/resolve/main/tools/target.py
- Command line
-
hf download hf://spaces/1990two/XTOOLS/tools/target.py
-
curl -L -o target.py https://huggingface.co/spaces/1990two/XTOOLS/resolve/main/tools/target.py
1.48 kB
| """ | |
| Target -- search scraper, parses embedded JSON blob. No auth. | |
| """ | |
| import re | |
| import json | |
| import time | |
| import httpx | |
| HEADERS = {"User-Agent": "Mozilla/5.0"} | |
| def run(params: dict) -> dict: | |
| keyword = params.get("keyword") | |
| if not keyword: | |
| raise ValueError("keyword is required") | |
| max_results = int(params.get("max_results", 25)) | |
| url = f"https://www.target.com/s?searchTerm={keyword}" | |
| last_err = None | |
| for attempt in range(3): | |
| try: | |
| resp = httpx.get(url, headers=HEADERS, timeout=20.0) | |
| resp.raise_for_status() | |
| break | |
| except Exception as e: | |
| last_err = e | |
| time.sleep(1.5 * (attempt + 1)) | |
| else: | |
| raise ValueError(f"Target request failed after retries: {last_err}") | |
| match = re.search(r'<script type="application/json"[^>]*id="__TGT_DATA__"[^>]*>(.*?)</script>', resp.text, re.S) | |
| if not match: | |
| return {"count": 0, "results": [], "note": "Could not locate embedded product JSON; page structure may have changed"} | |
| try: | |
| blob = json.loads(match.group(1)) | |
| except Exception: | |
| return {"count": 0, "results": [], "note": "Failed to parse embedded JSON"} | |
| # Target nests this deeply and the path shifts between deployments; | |
| # surfacing the raw blob keeps this usable without brittle path-chasing. | |
| return {"count": 0, "results": [], "raw_available": True, "note": "Parse __TGT_DATA__ product grid path for this deployment"} | |