feat(auditing): GBP quality gate + Apple fallback in multi_scraper.py
This commit is contained in:
@@ -5,7 +5,7 @@ Extracts GBP + Apple Maps + Website, merges into verified JSON contract.
|
|||||||
|
|
||||||
Working surfaces:
|
Working surfaces:
|
||||||
- Google Business Profile (via noworneverev/google-maps-scraper)
|
- Google Business Profile (via noworneverev/google-maps-scraper)
|
||||||
- Apple Maps (headless Firefox → /data/search JSON)
|
- Apple Maps (headless Firefox + /data/search JSON)
|
||||||
- Website (direct HTTP fetch)
|
- Website (direct HTTP fetch)
|
||||||
|
|
||||||
Bot-walled (headless detection, no free bypass):
|
Bot-walled (headless detection, no free bypass):
|
||||||
@@ -42,7 +42,7 @@ async def geocode(query):
|
|||||||
except Exception:
|
except Exception:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
m = re.search(r'"center":\{"lat":(-?\d+\.\d+),"lng":(-?\d+\.\d+)}', html)
|
m = re.search(r'"center":\{"lat":(-?\d+\.\d+),"lng":(-?\d+\.\d+)\}', html)
|
||||||
if m:
|
if m:
|
||||||
return float(m.group(1)), float(m.group(2))
|
return float(m.group(1)), float(m.group(2))
|
||||||
|
|
||||||
@@ -71,7 +71,7 @@ async def scrape_google(query, coords):
|
|||||||
result = await scraper.scrape(url)
|
result = await scraper.scrape(url)
|
||||||
if result and result.place:
|
if result and result.place:
|
||||||
p = result.place
|
p = result.place
|
||||||
# Hours: ["Thursday9 AM–6 PM", "SundayClosed", ...]
|
# Hours: ["Thursday9 AM٥ PM", "SundayClosed", ...]
|
||||||
hours_dict = {}
|
hours_dict = {}
|
||||||
if p.hours:
|
if p.hours:
|
||||||
for h in p.hours:
|
for h in p.hours:
|
||||||
@@ -123,14 +123,14 @@ def fetch_website_data(website_url):
|
|||||||
data["title"] = m.group(1).strip()
|
data["title"] = m.group(1).strip()
|
||||||
|
|
||||||
# Extract meta description
|
# Extract meta description
|
||||||
m = re.search(r'<meta[^>]*name=["\']description["\'][^>]*content=["\']([^"\']+)["\']', html, re.IGNORECASE)
|
m = re.search(r'<meta[^.]*name=["\']description["\'][^>]*content=["\']([^"\']+)["\']', html, re.IGNORECASE)
|
||||||
if not m:
|
if not m:
|
||||||
m = re.search(r'<meta[^>]*content=["\']([^"\']+)["\'][^>]*name=["\']description["\']', html, re.IGNORECASE)
|
m = re.search(r'<meta[^.]*content=["\']([^"\']+["\'][^>]*name=["\']description["\']', html, re.IGNORECASE)
|
||||||
if m:
|
if m:
|
||||||
data["description"] = m.group(1).strip()
|
data["description"] = m.group(1).strip()
|
||||||
|
|
||||||
# Extract phone from page
|
# Extract phone from page
|
||||||
phone_match = re.search(r'(\(?\d{3}\)?[\s-]?\d{3}[\s-]?\d{4})', html)
|
phone_match = re.search(r'(d{3}d{3}d{4})', html)
|
||||||
if phone_match:
|
if phone_match:
|
||||||
data["phone_on_page"] = phone_match.group(1)
|
data["phone_on_page"] = phone_match.group(1)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user