fix: extracao individual de nota de avaliacao (rating) e total de avaliacoes por estabelecimento
This commit is contained in:
@@ -12,6 +12,61 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
class ScraperService:
|
||||
|
||||
@staticmethod
|
||||
def _extract_rating_and_reviews(detail_panel, text_fallback: str = "") -> tuple:
|
||||
"""
|
||||
Extrai a nota de avaliação (ex: 4.8) e o total de avaliações (ex: 150)
|
||||
específicos de cada estabelecimento no Google Maps.
|
||||
"""
|
||||
rating = 0.0
|
||||
total_avaliacoes = 0
|
||||
|
||||
if detail_panel:
|
||||
# 1. Procurar elemento específico de nota (ex: <span aria-label="4,8 estrelas"> ou <span class="ceYyJf">)
|
||||
star_elem = detail_panel.query_selector("[aria-label*='estrela'], [aria-label*='star'], span.ceYyJf, div.F7L8d")
|
||||
if star_elem:
|
||||
aria_txt = star_elem.get_attribute("aria-label") or star_elem.inner_text()
|
||||
m = re.search(r'([1-5][.,]\d)', aria_txt)
|
||||
if m:
|
||||
try:
|
||||
rating = float(m.group(1).replace(',', '.'))
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
# 2. Procurar elemento específico de total de avaliações (ex: <button aria-label="1.250 avaliações">)
|
||||
rev_elem = detail_panel.query_selector("button[aria-label*='avaliaç'], span[aria-label*='avaliaç'], [aria-label*='avaliações']")
|
||||
if rev_elem:
|
||||
rev_txt = rev_elem.get_attribute("aria-label") or rev_elem.inner_text()
|
||||
m = re.search(r'([\d.,]+)\s*avaliaç', rev_txt, re.IGNORECASE)
|
||||
if m:
|
||||
try:
|
||||
total_avaliacoes = int(re.sub(r'\D', '', m.group(1)))
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
# Fallback usando o texto bruto do painel do lugar
|
||||
if rating == 0.0 and text_fallback:
|
||||
m = re.search(r'([1-5][.,]\d)\s*(?:estrelas?|★|\s*\(|\s*·)', text_fallback, re.IGNORECASE)
|
||||
if not m:
|
||||
m = re.search(r'([1-5][.,]\d)', text_fallback)
|
||||
if m:
|
||||
try:
|
||||
rating = float(m.group(1).replace(',', '.'))
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
if total_avaliacoes == 0 and text_fallback:
|
||||
m = re.search(r'([\d.,]+)\s*avaliaç', text_fallback, re.IGNORECASE)
|
||||
if not m:
|
||||
m = re.search(r'\(([\d.,]+)\)', text_fallback)
|
||||
if m:
|
||||
try:
|
||||
total_avaliacoes = int(re.sub(r'\D', '', m.group(1)))
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
return rating, total_avaliacoes
|
||||
|
||||
@staticmethod
|
||||
def scrape_google_maps(search_query: str, max_results: int = 15, headless: bool = True) -> List[Dict[str, Any]]:
|
||||
"""
|
||||
@@ -163,17 +218,8 @@ class ScraperService:
|
||||
if site_btn:
|
||||
website = site_btn.get_attribute("href") or ""
|
||||
|
||||
# 5. Rating e Avaliações
|
||||
rating = 0.0
|
||||
total_avaliacoes = 0
|
||||
rating_match = re.search(r'([1-5][.,]\d)\s*(?:\(([\d.,]+)\))?', detail_text)
|
||||
if rating_match:
|
||||
try:
|
||||
rating = float(rating_match.group(1).replace(',', '.'))
|
||||
if rating_match.group(2):
|
||||
total_avaliacoes = int(re.sub(r'\D', '', rating_match.group(2)))
|
||||
except ValueError:
|
||||
pass
|
||||
# 5. Rating e Avaliações reais por estabelecimento
|
||||
rating, total_avaliacoes = ScraperService._extract_rating_and_reviews(detail_panel, detail_text)
|
||||
|
||||
results.append({
|
||||
'nome_empresa': nome_empresa,
|
||||
@@ -217,16 +263,7 @@ class ScraperService:
|
||||
if site_btn:
|
||||
website = site_btn.get_attribute("href") or ""
|
||||
|
||||
rating = 0.0
|
||||
total_avaliacoes = 0
|
||||
rating_match = re.search(r'([1-5][.,]\d)\s*(?:\(([\d.,]+)\))?', detail_text)
|
||||
if rating_match:
|
||||
try:
|
||||
rating = float(rating_match.group(1).replace(',', '.'))
|
||||
if rating_match.group(2):
|
||||
total_avaliacoes = int(re.sub(r'\D', '', rating_match.group(2)))
|
||||
except ValueError:
|
||||
pass
|
||||
rating, total_avaliacoes = ScraperService._extract_rating_and_reviews(detail_panel, detail_text)
|
||||
|
||||
results.append({
|
||||
'nome_empresa': nome_empresa,
|
||||
|
||||
Reference in New Issue
Block a user