Mayrasilva's picture
Upload app.py
e9dfeb6 verified
Raw
History Blame Contribute Delete
8.45 kB
import gradio as gr
import requests
from bs4 import BeautifulSoup
import json
from datetime import datetime
def calculate_trust_score(url):
try:
if not url.startswith(('http://', 'https://')):
url = 'https://' + url
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
}
response = requests.get(url, headers=headers, timeout=10)
soup = BeautifulSoup(response.text, 'html.parser')
trust_score = 0
details = {
'identity': {'score': 0, 'max': 40, 'items': []},
'content': {'score': 0, 'max': 40, 'items': []},
'signals': {'score': 0, 'max': 20, 'items': []}
}
scripts = soup.find_all('script', type='application/ld+json')
has_organization = False
has_person = False
has_same_as = False
for script in scripts:
try:
data = json.loads(script.string)
data_items = data if isinstance(data, list) else [data]
for item in data_items:
if "@type" in item:
if item["@type"] == "Organization":
has_organization = True
details['identity']['score'] += 15
details['identity']['items'].append("✅ Organização identificada")
if "logo" in item:
details['identity']['score'] += 5
details['identity']['items'].append("✅ Logo definida")
if "sameAs" in item:
has_same_as = True
details['identity']['score'] += 10
details['identity']['items'].append("✅ Links de verificação (sameAs)")
elif item["@type"] == "Person":
has_person = True
details['identity']['score'] += 10
details['identity']['items'].append("✅ Pessoa identificada")
if "sameAs" in item:
has_same_as = True
details['identity']['score'] += 10
details['identity']['items'].append("✅ Links sociais da pessoa")
elif item["@type"] == "Article":
details['content']['score'] += 15
details['content']['items'].append("✅ Artigo estruturado")
if "author" in item:
details['content']['score'] += 10
details['content']['items'].append("✅ Autor identificado")
if "datePublished" in item:
details['content']['score'] += 5
details['content']['items'].append("✅ Data de publicação")
except:
continue
h1_count = len(soup.find_all('h1'))
h2_count = len(soup.find_all('h2'))
if h1_count == 1:
details['content']['score'] += 5
details['content']['items'].append("✅ Estrutura H1 única")
elif h1_count > 1:
details['content']['items'].append("⚠️ Múltiplos H1 encontrados")
if h2_count > 0:
details['content']['score'] += 5
details['content']['items'].append("✅ Estrutura H2 presente")
title = soup.find('title')
meta_desc = soup.find('meta', attrs={'name': 'description'})
if title and len(title.get_text().strip()) > 10:
details['content']['score'] += 5
details['content']['items'].append("✅ Título adequado")
if meta_desc and len(meta_desc.get('content', '').strip()) > 50:
details['content']['score'] += 5
details['content']['items'].append("✅ Meta description presente")
if url.startswith('https://'):
details['signals']['score'] += 10
details['signals']['items'].append("✅ HTTPS ativo")
contact_indicators = ['contact', 'email', 'phone', 'address', 'sobre', 'about']
page_text = soup.get_text().lower()
if any(indicator in page_text for indicator in contact_indicators):
details['signals']['score'] += 5
details['signals']['items'].append("✅ Informações de contato")
external_links = soup.find_all('a', href=True)
quality_domains = ['github.com', 'linkedin.com', 'medium.com', 'wikidata.org', 'keybase.io']
for link in external_links:
href = link.get('href', '')
if any(domain in href for domain in quality_domains):
details['signals']['score'] += 5
details['signals']['items'].append("✅ Links para plataformas confiáveis")
break
total_score = min(
details['identity']['score'] +
details['content']['score'] +
details['signals']['score'],
100
)
if total_score >= 80:
level = "🚀 Excelente"
level_color = "🟢"
elif total_score >= 60:
level = "👍 Bom"
level_color = "🟡"
elif total_score >= 40:
level = "⚠️ Precisa melhorar"
level_color = "🟠"
else:
level = "❌ Crítico"
level_color = "🔴"
suggestions = []
if not has_organization and not has_person:
suggestions.append("🎯 **Prioridade Alta**: Adicione schema.org com @type Organization ou Person")
if not has_same_as:
suggestions.append("🔗 Adicione links 'sameAs' para LinkedIn, GitHub ou outras plataformas")
if details['content']['score'] < 20:
suggestions.append("📝 Melhore a estrutura do conteúdo com headings H1/H2 e meta tags")
if details['signals']['score'] < 10:
suggestions.append("🔒 Garanta HTTPS e adicione informações de contato")
if total_score >= 80:
suggestions.append("🎉 Parabéns! Seu site está bem otimizado para LLMs")
report = f"""# {level_color} **Trust Score: {total_score}/100**
## {level}
### 📊 **Detalhamento por Categoria**
#### 🏢 **Identidade Digital** ({details['identity']['score']}/{details['identity']['max']} pontos)
{chr(10).join(details['identity']['items']) if details['identity']['items'] else "❌ Nenhuma identidade estruturada encontrada"}
#### 📝 **Conteúdo Estruturado** ({details['content']['score']}/{details['content']['max']} pontos)
{chr(10).join(details['content']['items']) if details['content']['items'] else "❌ Estrutura de conteúdo não otimizada"}
#### 🔒 **Sinais de Confiança** ({details['signals']['score']}/{details['signals']['max']} pontos)
{chr(10).join(details['signals']['items']) if details['signals']['items'] else "❌ Sinais de confiança ausentes"}
### 💡 **Próximos Passos**
{chr(10).join(f"• {tip}" for tip in suggestions)}
### 📚 **Recursos Úteis**
• [Schema.org Generator](https://schema.org/)
• [Google Rich Results Test](https://search.google.com/test/rich-results)
• [Structured Data Markup Helper](https://www.google.com/webmasters/markup-helper/)
-----
*💡 Dica: Um site bem estruturado não só melhora a visibilidade para LLMs, mas também para mecanismos de busca!*
"""
return report
except requests.exceptions.RequestException as e:
return f"❌ **Erro de conexão**: Não foi possível acessar o site.\n\n*Verifique se a URL está correta e o site está online.*"
except Exception as e:
return f"❌ **Erro inesperado**: {str(e)}\n\n*Tente novamente ou verifique se a URL está no formato correto.*"
import gradio as gr
with gr.Blocks(title="🤖 LLM Trust Score") as demo:
gr.Markdown("## 🤖 LLM Trust Score Calculator\nDescubra como seu site é percebido por modelos como ChatGPT, Claude, Perplexity e Grok.")
url_input = gr.Textbox(label="🌐 URL do seu site", placeholder="exemplo.com ou https://seusite.com.br")
output = gr.Markdown()
analyze_btn = gr.Button("🔍 Analisar Site")
analyze_btn.click(fn=calculate_trust_score, inputs=url_input, outputs=output)
demo.launch()