Compare commits
11 Commits
6426f97831
...
115c1c1193
| Author | SHA1 | Date | |
|---|---|---|---|
| 115c1c1193 | |||
| 06c22539d7 | |||
| 3d69d53550 | |||
| 9cd5066afe | |||
| ee6bc656ef | |||
| c057794c64 | |||
| 3bdbde1621 | |||
| b389287697 | |||
| 4110ef63b5 | |||
| 1426a73e0d | |||
| c8d9d295af |
25
.auto-claude-status
Normal file
25
.auto-claude-status
Normal file
@ -0,0 +1,25 @@
|
||||
{
|
||||
"active": true,
|
||||
"spec": "007-https-nordabiznes-pl-audit-gbp-inpi-dane-nie-sa-w-",
|
||||
"state": "building",
|
||||
"subtasks": {
|
||||
"completed": 12,
|
||||
"total": 14,
|
||||
"in_progress": 1,
|
||||
"failed": 0
|
||||
},
|
||||
"phase": {
|
||||
"current": "DEV Verification",
|
||||
"id": null,
|
||||
"total": 4
|
||||
},
|
||||
"workers": {
|
||||
"active": 0,
|
||||
"max": 1
|
||||
},
|
||||
"session": {
|
||||
"number": 13,
|
||||
"started_at": "2026-01-08T20:23:31.762031"
|
||||
},
|
||||
"last_update": "2026-01-08T20:50:25.874452"
|
||||
}
|
||||
@ -20,6 +20,12 @@ GOOGLE_GEMINI_API_KEY=your_gemini_api_key_here
|
||||
# Free tier: 25,000 requests/day
|
||||
GOOGLE_PAGESPEED_API_KEY=your_pagespeed_api_key_here
|
||||
|
||||
# Google Places API (for GBP audits - Google Business Profile)
|
||||
# Get your API key from: https://console.cloud.google.com/apis/credentials
|
||||
# Enable "Places API" in Google Cloud Console
|
||||
# Free tier: $200/month credit (covers ~10,000 requests)
|
||||
GOOGLE_PLACES_API_KEY=your_places_api_key_here
|
||||
|
||||
# Email Configuration (for user verification)
|
||||
MAIL_SERVER=smtp.gmail.com
|
||||
MAIL_PORT=587
|
||||
|
||||
@ -17,6 +17,9 @@ psycopg2-binary==2.9.9
|
||||
# Google Gemini AI
|
||||
google-generativeai==0.3.2
|
||||
|
||||
# Google Maps/Places API
|
||||
googlemaps==4.10.0
|
||||
|
||||
# Environment Configuration
|
||||
python-dotenv==1.0.0
|
||||
|
||||
|
||||
@ -33,6 +33,20 @@ from datetime import datetime, timedelta
|
||||
from typing import Optional, Dict, List, Tuple, Any
|
||||
from urllib.parse import urlparse
|
||||
import time
|
||||
from pathlib import Path
|
||||
|
||||
# Load .env file from project root
|
||||
try:
|
||||
from dotenv import load_dotenv
|
||||
# Find .env file relative to this script
|
||||
script_dir = Path(__file__).resolve().parent
|
||||
project_root = script_dir.parent
|
||||
env_path = project_root / '.env'
|
||||
if env_path.exists():
|
||||
load_dotenv(env_path)
|
||||
logging.info(f"Loaded .env from {env_path}")
|
||||
except ImportError:
|
||||
pass # python-dotenv not installed, rely on system environment
|
||||
|
||||
import requests
|
||||
from bs4 import BeautifulSoup
|
||||
@ -408,9 +422,9 @@ class WebsiteAuditor:
|
||||
if matches:
|
||||
# Get first valid match, excluding common false positives
|
||||
for match in matches:
|
||||
# Check against exclusion list
|
||||
# Check against exclusion list (exact match only to avoid false positives)
|
||||
excludes = SOCIAL_MEDIA_EXCLUDE.get(platform, [])
|
||||
if match.lower() not in excludes and not any(ex in match.lower() for ex in excludes):
|
||||
if match.lower() not in excludes:
|
||||
# Construct full URL
|
||||
if platform == 'facebook':
|
||||
url = f'https://facebook.com/{match}'
|
||||
@ -439,6 +453,207 @@ class WebsiteAuditor:
|
||||
return result
|
||||
|
||||
|
||||
class GooglePlacesSearcher:
|
||||
"""Search for Google Business profiles using Google Places API."""
|
||||
|
||||
# Google Places API configuration
|
||||
FIND_PLACE_URL = 'https://maps.googleapis.com/maps/api/place/findplacefromtext/json'
|
||||
PLACE_DETAILS_URL = 'https://maps.googleapis.com/maps/api/place/details/json'
|
||||
|
||||
def __init__(self, api_key: Optional[str] = None):
|
||||
"""
|
||||
Initialize GooglePlacesSearcher.
|
||||
|
||||
Args:
|
||||
api_key: Google Places API key. Falls back to GOOGLE_PLACES_API_KEY env var.
|
||||
"""
|
||||
self.api_key = api_key or os.getenv('GOOGLE_PLACES_API_KEY')
|
||||
self.session = requests.Session()
|
||||
self.session.headers.update({'User-Agent': USER_AGENT})
|
||||
|
||||
def find_place(self, company_name: str, city: str = 'Wejherowo') -> Optional[str]:
|
||||
"""
|
||||
Find a place by company name and city.
|
||||
|
||||
Uses Google Places findplacefromtext API to search for a business
|
||||
and returns the place_id if found.
|
||||
|
||||
Args:
|
||||
company_name: Name of the company to search for.
|
||||
city: City to narrow down the search (default: Wejherowo).
|
||||
|
||||
Returns:
|
||||
place_id string if found, None otherwise.
|
||||
"""
|
||||
if not self.api_key:
|
||||
logger.warning('Google Places API key not configured')
|
||||
return None
|
||||
|
||||
try:
|
||||
# Construct search query with company name and city
|
||||
search_query = f'{company_name} {city}'
|
||||
|
||||
params = {
|
||||
'input': search_query,
|
||||
'inputtype': 'textquery',
|
||||
'fields': 'place_id,name,formatted_address',
|
||||
'language': 'pl',
|
||||
'key': self.api_key,
|
||||
}
|
||||
|
||||
response = self.session.get(
|
||||
self.FIND_PLACE_URL,
|
||||
params=params,
|
||||
timeout=REQUEST_TIMEOUT
|
||||
)
|
||||
response.raise_for_status()
|
||||
|
||||
data = response.json()
|
||||
|
||||
if data.get('status') == 'OK' and data.get('candidates'):
|
||||
candidate = data['candidates'][0]
|
||||
place_id = candidate.get('place_id')
|
||||
logger.info(
|
||||
f"Found place for '{company_name}': {candidate.get('name')} "
|
||||
f"at {candidate.get('formatted_address')}"
|
||||
)
|
||||
return place_id
|
||||
elif data.get('status') == 'ZERO_RESULTS':
|
||||
logger.info(f"No Google Business Profile found for '{company_name}' in {city}")
|
||||
return None
|
||||
else:
|
||||
logger.warning(
|
||||
f"Google Places API returned status: {data.get('status')} "
|
||||
f"for '{company_name}'"
|
||||
)
|
||||
return None
|
||||
|
||||
except requests.exceptions.Timeout:
|
||||
logger.error(f"Timeout searching for '{company_name}' on Google Places")
|
||||
return None
|
||||
except requests.exceptions.RequestException as e:
|
||||
logger.error(f"Request error searching for '{company_name}': {e}")
|
||||
return None
|
||||
except Exception as e:
|
||||
logger.error(f"Error finding place for '{company_name}': {e}")
|
||||
return None
|
||||
|
||||
def get_place_details(self, place_id: str) -> Dict[str, Any]:
|
||||
"""
|
||||
Get detailed information about a place.
|
||||
|
||||
Retrieves rating, review count, opening hours, and other business details
|
||||
from Google Places API.
|
||||
|
||||
Args:
|
||||
place_id: Google Place ID returned from find_place().
|
||||
|
||||
Returns:
|
||||
Dict containing:
|
||||
- google_rating: Decimal rating (1.0-5.0) or None
|
||||
- google_reviews_count: Integer review count or None
|
||||
- opening_hours: Dict with weekday_text and open_now, or None
|
||||
- business_status: String like 'OPERATIONAL', 'CLOSED_TEMPORARILY', etc.
|
||||
- formatted_phone: Phone number or None
|
||||
- website: Website URL or None
|
||||
"""
|
||||
result = {
|
||||
'google_rating': None,
|
||||
'google_reviews_count': None,
|
||||
'opening_hours': None,
|
||||
'business_status': None,
|
||||
'formatted_phone': None,
|
||||
'website': None,
|
||||
}
|
||||
|
||||
if not self.api_key:
|
||||
logger.warning('Google Places API key not configured')
|
||||
return result
|
||||
|
||||
if not place_id:
|
||||
return result
|
||||
|
||||
try:
|
||||
# Request fields we need for the audit
|
||||
fields = [
|
||||
'rating',
|
||||
'user_ratings_total',
|
||||
'opening_hours',
|
||||
'business_status',
|
||||
'formatted_phone_number',
|
||||
'website',
|
||||
'name',
|
||||
]
|
||||
|
||||
params = {
|
||||
'place_id': place_id,
|
||||
'fields': ','.join(fields),
|
||||
'language': 'pl',
|
||||
'key': self.api_key,
|
||||
}
|
||||
|
||||
response = self.session.get(
|
||||
self.PLACE_DETAILS_URL,
|
||||
params=params,
|
||||
timeout=REQUEST_TIMEOUT
|
||||
)
|
||||
response.raise_for_status()
|
||||
|
||||
data = response.json()
|
||||
|
||||
if data.get('status') == 'OK' and data.get('result'):
|
||||
place = data['result']
|
||||
|
||||
# Extract rating
|
||||
if 'rating' in place:
|
||||
result['google_rating'] = round(float(place['rating']), 1)
|
||||
|
||||
# Extract review count
|
||||
if 'user_ratings_total' in place:
|
||||
result['google_reviews_count'] = int(place['user_ratings_total'])
|
||||
|
||||
# Extract opening hours
|
||||
if 'opening_hours' in place:
|
||||
hours = place['opening_hours']
|
||||
result['opening_hours'] = {
|
||||
'weekday_text': hours.get('weekday_text', []),
|
||||
'open_now': hours.get('open_now'),
|
||||
'periods': hours.get('periods', []),
|
||||
}
|
||||
|
||||
# Extract business status
|
||||
if 'business_status' in place:
|
||||
result['business_status'] = place['business_status']
|
||||
|
||||
# Extract phone
|
||||
if 'formatted_phone_number' in place:
|
||||
result['formatted_phone'] = place['formatted_phone_number']
|
||||
|
||||
# Extract website
|
||||
if 'website' in place:
|
||||
result['website'] = place['website']
|
||||
|
||||
logger.info(
|
||||
f"Retrieved details for {place.get('name')}: "
|
||||
f"rating={result['google_rating']}, "
|
||||
f"reviews={result['google_reviews_count']}"
|
||||
)
|
||||
else:
|
||||
logger.warning(
|
||||
f"Google Places API returned status: {data.get('status')} "
|
||||
f"for place_id: {place_id}"
|
||||
)
|
||||
|
||||
except requests.exceptions.Timeout:
|
||||
logger.error(f"Timeout getting details for place_id: {place_id}")
|
||||
except requests.exceptions.RequestException as e:
|
||||
logger.error(f"Request error getting place details: {e}")
|
||||
except Exception as e:
|
||||
logger.error(f"Error getting place details for {place_id}: {e}")
|
||||
|
||||
return result
|
||||
|
||||
|
||||
class BraveSearcher:
|
||||
"""Search for social media profiles and Google reviews using Brave Search."""
|
||||
|
||||
@ -475,24 +690,150 @@ class BraveSearcher:
|
||||
|
||||
def search_google_reviews(self, company_name: str, city: str = 'Wejherowo') -> Dict[str, Any]:
|
||||
"""
|
||||
Search for Google reviews via Brave.
|
||||
Returns dict with rating, reviews_count.
|
||||
Search for Google reviews using Google Places API.
|
||||
|
||||
This method uses the GooglePlacesSearcher to find the company on Google
|
||||
and retrieve its rating and review count.
|
||||
|
||||
Args:
|
||||
company_name: Name of the company to search for.
|
||||
city: City to narrow down the search (default: Wejherowo).
|
||||
|
||||
Returns:
|
||||
Dict containing:
|
||||
- google_rating: Decimal rating (1.0-5.0) or None
|
||||
- google_reviews_count: Integer review count or None
|
||||
- opening_hours: Dict with weekday_text and open_now, or None
|
||||
- business_status: String like 'OPERATIONAL', 'CLOSED_TEMPORARILY', etc.
|
||||
"""
|
||||
result = {
|
||||
'google_rating': None,
|
||||
'google_reviews_count': None,
|
||||
'opening_hours': None,
|
||||
'business_status': None,
|
||||
}
|
||||
|
||||
try:
|
||||
query = f'{company_name} {city} opinie google'
|
||||
# This would use Brave API or scraping
|
||||
# For now, placeholder
|
||||
pass
|
||||
# Use Google Places API for accurate data
|
||||
google_api_key = os.getenv('GOOGLE_PLACES_API_KEY')
|
||||
|
||||
if google_api_key:
|
||||
# Use GooglePlacesSearcher for accurate data retrieval
|
||||
places_searcher = GooglePlacesSearcher(api_key=google_api_key)
|
||||
|
||||
# Step 1: Find the place by company name and city
|
||||
place_id = places_searcher.find_place(company_name, city)
|
||||
|
||||
if place_id:
|
||||
# Step 2: Get detailed information including reviews
|
||||
details = places_searcher.get_place_details(place_id)
|
||||
|
||||
result['google_rating'] = details.get('google_rating')
|
||||
result['google_reviews_count'] = details.get('google_reviews_count')
|
||||
result['opening_hours'] = details.get('opening_hours')
|
||||
result['business_status'] = details.get('business_status')
|
||||
|
||||
logger.info(
|
||||
f"Google reviews for '{company_name}': "
|
||||
f"rating={result['google_rating']}, "
|
||||
f"reviews={result['google_reviews_count']}, "
|
||||
f"status={result['business_status']}"
|
||||
)
|
||||
else:
|
||||
logger.info(f"No Google Business Profile found for '{company_name}' in {city}")
|
||||
else:
|
||||
# Fallback: Try Brave Search API if available
|
||||
if self.api_key:
|
||||
brave_result = self._search_brave_for_reviews(company_name, city)
|
||||
if brave_result:
|
||||
result.update(brave_result)
|
||||
else:
|
||||
logger.warning(
|
||||
'Neither GOOGLE_PLACES_API_KEY nor BRAVE_API_KEY configured. '
|
||||
'Cannot retrieve Google reviews data.'
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
logger.warning(f'Google reviews search failed: {e}')
|
||||
logger.warning(f'Google reviews search failed for {company_name}: {e}')
|
||||
|
||||
return result
|
||||
|
||||
def _search_brave_for_reviews(self, company_name: str, city: str) -> Optional[Dict[str, Any]]:
|
||||
"""
|
||||
Fallback method to search for Google reviews via Brave Search API.
|
||||
|
||||
This parses search results to extract rating and review count from
|
||||
Google Business snippets in search results.
|
||||
|
||||
Args:
|
||||
company_name: Name of the company.
|
||||
city: City for location context.
|
||||
|
||||
Returns:
|
||||
Dict with google_rating and google_reviews_count, or None if not found.
|
||||
"""
|
||||
if not self.api_key:
|
||||
return None
|
||||
|
||||
try:
|
||||
query = f'{company_name} {city} opinie google'
|
||||
|
||||
# Brave Web Search API endpoint
|
||||
url = 'https://api.search.brave.com/res/v1/web/search'
|
||||
headers = {
|
||||
'Accept': 'application/json',
|
||||
'Accept-Encoding': 'gzip',
|
||||
'X-Subscription-Token': self.api_key,
|
||||
}
|
||||
params = {
|
||||
'q': query,
|
||||
'count': 10,
|
||||
'country': 'pl',
|
||||
'search_lang': 'pl',
|
||||
'ui_lang': 'pl-PL',
|
||||
}
|
||||
|
||||
response = self.session.get(url, headers=headers, params=params, timeout=REQUEST_TIMEOUT)
|
||||
response.raise_for_status()
|
||||
|
||||
data = response.json()
|
||||
|
||||
# Parse search results for rating/review patterns
|
||||
# Google snippets often contain patterns like "4,5 (123 opinii)" or "Rating: 4.5 · 123 reviews"
|
||||
for result in data.get('web', {}).get('results', []):
|
||||
snippet = result.get('description', '') + ' ' + result.get('title', '')
|
||||
|
||||
# Pattern for Polish Google reviews: "4,5 (123 opinii)" or "4.5 · 123 reviews"
|
||||
rating_patterns = [
|
||||
r'(\d+[,\.]\d)\s*[·\(]\s*(\d+)\s*(?:opinii|recenzji|reviews)',
|
||||
r'ocena[:\s]+(\d+[,\.]\d).*?(\d+)\s*(?:opinii|recenzji)',
|
||||
r'rating[:\s]+(\d+[,\.]\d).*?(\d+)\s*(?:reviews|opinii)',
|
||||
]
|
||||
|
||||
for pattern in rating_patterns:
|
||||
match = re.search(pattern, snippet, re.IGNORECASE)
|
||||
if match:
|
||||
rating_str = match.group(1).replace(',', '.')
|
||||
reviews_str = match.group(2)
|
||||
|
||||
return {
|
||||
'google_rating': round(float(rating_str), 1),
|
||||
'google_reviews_count': int(reviews_str),
|
||||
}
|
||||
|
||||
logger.info(f"No Google reviews data found in Brave results for '{company_name}'")
|
||||
return None
|
||||
|
||||
except requests.exceptions.Timeout:
|
||||
logger.warning(f"Timeout searching Brave for '{company_name}' reviews")
|
||||
return None
|
||||
except requests.exceptions.RequestException as e:
|
||||
logger.warning(f"Brave API request failed for '{company_name}': {e}")
|
||||
return None
|
||||
except Exception as e:
|
||||
logger.warning(f"Error parsing Brave results for '{company_name}': {e}")
|
||||
return None
|
||||
|
||||
def _search_brave(self, query: str, platform: str) -> Optional[str]:
|
||||
"""
|
||||
Perform Brave search and extract relevant URL.
|
||||
@ -512,6 +853,15 @@ class SocialMediaAuditor:
|
||||
self.website_auditor = WebsiteAuditor()
|
||||
self.brave_searcher = BraveSearcher()
|
||||
|
||||
# Initialize Google Places searcher if API key is available
|
||||
google_places_api_key = os.getenv('GOOGLE_PLACES_API_KEY')
|
||||
if google_places_api_key:
|
||||
self.google_places_searcher = GooglePlacesSearcher(api_key=google_places_api_key)
|
||||
logger.info('Google Places API key found - using Places API for reviews')
|
||||
else:
|
||||
self.google_places_searcher = None
|
||||
logger.info('GOOGLE_PLACES_API_KEY not set - falling back to Brave Search for reviews')
|
||||
|
||||
def get_companies(self, company_ids: Optional[List[int]] = None,
|
||||
batch_start: Optional[int] = None,
|
||||
batch_end: Optional[int] = None) -> List[Dict]:
|
||||
@ -546,6 +896,18 @@ class SocialMediaAuditor:
|
||||
|
||||
return [dict(row._mapping) for row in result]
|
||||
|
||||
def get_company_id_by_slug(self, slug: str) -> Optional[int]:
|
||||
"""Get company ID by slug."""
|
||||
with self.Session() as session:
|
||||
query = text("""
|
||||
SELECT id FROM companies WHERE slug = :slug
|
||||
""")
|
||||
result = session.execute(query, {'slug': slug})
|
||||
row = result.fetchone()
|
||||
if row:
|
||||
return row[0]
|
||||
return None
|
||||
|
||||
def audit_company(self, company: Dict) -> Dict[str, Any]:
|
||||
"""
|
||||
Perform full audit for a single company.
|
||||
@ -589,8 +951,28 @@ class SocialMediaAuditor:
|
||||
|
||||
result['social_media'] = website_social
|
||||
|
||||
# 4. Google reviews search
|
||||
# 4. Google reviews search - prefer Google Places API if available
|
||||
try:
|
||||
if self.google_places_searcher:
|
||||
# Use Google Places API directly for accurate data
|
||||
place_id = self.google_places_searcher.find_place(company['name'], city)
|
||||
if place_id:
|
||||
details = self.google_places_searcher.get_place_details(place_id)
|
||||
result['google_reviews'] = {
|
||||
'google_rating': details.get('google_rating'),
|
||||
'google_reviews_count': details.get('google_reviews_count'),
|
||||
'opening_hours': details.get('opening_hours'),
|
||||
'business_status': details.get('business_status'),
|
||||
}
|
||||
else:
|
||||
result['google_reviews'] = {
|
||||
'google_rating': None,
|
||||
'google_reviews_count': None,
|
||||
'opening_hours': None,
|
||||
'business_status': None,
|
||||
}
|
||||
else:
|
||||
# Fallback to Brave Search
|
||||
result['google_reviews'] = self.brave_searcher.search_google_reviews(
|
||||
company['name'], city
|
||||
)
|
||||
@ -755,6 +1137,7 @@ class SocialMediaAuditor:
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description='Social Media & Website Audit')
|
||||
parser.add_argument('--company-id', type=int, help='Audit single company by ID')
|
||||
parser.add_argument('--company-slug', type=str, help='Audit single company by slug')
|
||||
parser.add_argument('--batch', type=str, help='Audit batch of companies (e.g., 1-10)')
|
||||
parser.add_argument('--all', action='store_true', help='Audit all companies')
|
||||
parser.add_argument('--dry-run', action='store_true', help='Print results without saving')
|
||||
@ -769,6 +1152,14 @@ def main():
|
||||
|
||||
if args.company_id:
|
||||
summary = auditor.run_audit(company_ids=[args.company_id], dry_run=args.dry_run)
|
||||
elif args.company_slug:
|
||||
# Look up company ID by slug
|
||||
company_id = auditor.get_company_id_by_slug(args.company_slug)
|
||||
if company_id:
|
||||
summary = auditor.run_audit(company_ids=[company_id], dry_run=args.dry_run)
|
||||
else:
|
||||
print(f"Error: Company with slug '{args.company_slug}' not found")
|
||||
sys.exit(1)
|
||||
elif args.batch:
|
||||
start, end = map(int, args.batch.split('-'))
|
||||
summary = auditor.run_audit(batch_start=start, batch_end=end, dry_run=args.dry_run)
|
||||
|
||||
120
scripts/verify_google_places.py
Normal file
120
scripts/verify_google_places.py
Normal file
@ -0,0 +1,120 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Verify Google Places API integration for social_media_audit.py.
|
||||
|
||||
This script tests the GooglePlacesSearcher class directly without
|
||||
requiring database access.
|
||||
"""
|
||||
import os
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
# Add user site-packages to path
|
||||
sys.path.insert(0, '/Users/maciejpi/Library/Python/3.9/lib/python/site-packages')
|
||||
|
||||
# Load .env file from project root
|
||||
try:
|
||||
from dotenv import load_dotenv
|
||||
script_dir = Path(__file__).resolve().parent
|
||||
project_root = script_dir.parent
|
||||
env_path = project_root / '.env'
|
||||
if env_path.exists():
|
||||
load_dotenv(env_path)
|
||||
print(f"Loaded .env from {env_path}")
|
||||
except ImportError:
|
||||
print("python-dotenv not installed, using system environment")
|
||||
|
||||
# Import GooglePlacesSearcher from social_media_audit
|
||||
from social_media_audit import GooglePlacesSearcher, BraveSearcher
|
||||
|
||||
def main():
|
||||
api_key = os.getenv('GOOGLE_PLACES_API_KEY')
|
||||
print(f"\nGoogle Places API Key: {'*' * 10 + api_key[-8:] if api_key else 'NOT SET'}")
|
||||
|
||||
if not api_key or api_key == 'your_places_api_key_here':
|
||||
print("ERROR: GOOGLE_PLACES_API_KEY not configured in .env")
|
||||
sys.exit(1)
|
||||
|
||||
# Test GooglePlacesSearcher directly
|
||||
print("\n" + "=" * 60)
|
||||
print("Testing GooglePlacesSearcher for INPI company")
|
||||
print("=" * 60)
|
||||
|
||||
searcher = GooglePlacesSearcher(api_key=api_key)
|
||||
|
||||
# Step 1: Find place
|
||||
print("\n1. Finding place for 'INPI' in Wejherowo...")
|
||||
place_id = searcher.find_place('INPI', 'Wejherowo')
|
||||
|
||||
if not place_id:
|
||||
print(" ERROR: Could not find INPI on Google Places")
|
||||
print(" This could mean:")
|
||||
print(" - The company doesn't have a Google Business Profile")
|
||||
print(" - The API key doesn't have Places API enabled")
|
||||
print(" - The search query needs adjustment")
|
||||
sys.exit(1)
|
||||
|
||||
print(f" Found place_id: {place_id}")
|
||||
|
||||
# Step 2: Get place details
|
||||
print("\n2. Getting place details...")
|
||||
details = searcher.get_place_details(place_id)
|
||||
|
||||
print(f"\n Results:")
|
||||
print(f" - google_rating: {details.get('google_rating')}")
|
||||
print(f" - google_reviews_count: {details.get('google_reviews_count')}")
|
||||
print(f" - business_status: {details.get('business_status')}")
|
||||
print(f" - opening_hours: {'Yes' if details.get('opening_hours') else 'Not available'}")
|
||||
|
||||
if details.get('opening_hours'):
|
||||
hours = details.get('opening_hours', {})
|
||||
if hours.get('weekday_text'):
|
||||
print(" - Hours:")
|
||||
for day in hours['weekday_text']:
|
||||
print(f" {day}")
|
||||
|
||||
# Step 3: Test via BraveSearcher.search_google_reviews
|
||||
print("\n" + "=" * 60)
|
||||
print("Testing BraveSearcher.search_google_reviews()")
|
||||
print("=" * 60)
|
||||
|
||||
brave = BraveSearcher()
|
||||
result = brave.search_google_reviews('INPI', 'Wejherowo')
|
||||
|
||||
print(f"\n Results:")
|
||||
print(f" - google_rating: {result.get('google_rating')}")
|
||||
print(f" - google_reviews_count: {result.get('google_reviews_count')}")
|
||||
print(f" - business_status: {result.get('business_status')}")
|
||||
print(f" - opening_hours: {'Yes' if result.get('opening_hours') else 'Not available'}")
|
||||
|
||||
# Verify expected data
|
||||
print("\n" + "=" * 60)
|
||||
print("VERIFICATION SUMMARY")
|
||||
print("=" * 60)
|
||||
|
||||
success = True
|
||||
|
||||
if result.get('google_rating') is not None:
|
||||
print(f"[PASS] google_rating present: {result['google_rating']}")
|
||||
else:
|
||||
print("[FAIL] google_rating is None")
|
||||
success = False
|
||||
|
||||
if result.get('google_reviews_count') is not None:
|
||||
print(f"[PASS] google_reviews_count present: {result['google_reviews_count']}")
|
||||
else:
|
||||
print("[FAIL] google_reviews_count is None")
|
||||
success = False
|
||||
|
||||
if success:
|
||||
print("\n[SUCCESS] Google Places API integration is working!")
|
||||
print("The social_media_audit.py can now collect Google reviews data.")
|
||||
else:
|
||||
print("\n[WARNING] Some data was not retrieved.")
|
||||
print("Check if the business has a Google Business Profile with reviews.")
|
||||
|
||||
return 0 if success else 1
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
||||
1206
tests/test_social_media_audit.py
Normal file
1206
tests/test_social_media_audit.py
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user