from datetime import datetime, timezone from typing import Tuple import urllib from gradio import List from pydantic import BaseModel import requests import wikipediaapi class Wikipedia_Historical_Page(BaseModel): title: str url: str revision_id: str timestamp: str class Wikipedia_Util: WIKI_LANG = 'en' # Linguagem da Wikipedia (atualizado para inglês) MEDIAWIKI_API_URL = f"https://{WIKI_LANG}.wikipedia.org/w/api.php" HEADERS = { 'User-Agent': 'MyCoolSearchBot/1.0 (manus@example.com)' } wiki_executor = wikipediaapi.Wikipedia( language=WIKI_LANG, extract_format=wikipediaapi.ExtractFormat.HTML, # Usado apenas para page.exists() user_agent='MyCoolSearchBot/1.0 (manus@example.com)' # Definir um User-Agent é boa prática ) @staticmethod def get_wikipedia_revision_info(page_title: str, target_date_str: str) -> Tuple[str,str]: """ Busca o ID e timestamp da revisão mais próxima (<=) da data fornecida via API MediaWiki. Args: page_title: wikipedia encontra páginas históricas pelo titulo target_date_str: data no formato "YYYY-MM-DD" Returns: Uma tupla contendo o ID da revisão e o timestamp da revisão. """ try: # Converte a data string para um objeto datetime e formata para ISO 8601 com Z (UTC) target_dt = datetime.strptime(target_date_str, '%Y-%m-%d') # Precisamos do final do dia para garantir que incluímos todas as revisões daquele dia target_dt_end_of_day = target_dt.replace(hour=23, minute=59, second=59, tzinfo=timezone.utc) target_timestamp_iso = target_dt_end_of_day.strftime('%Y-%m-%dT%H:%M:%SZ') except ValueError: print("Formato de data inválido. Use AAAA-MM-DD.") return None, None params = { "action": "query", "prop": "revisions", "titles": page_title, "rvlimit": 1, "rvdir": "older", # Busca a revisão imediatamente anterior ou igual ao timestamp "rvprop": "ids|timestamp", # Queremos o ID da revisão e o timestamp "rvstart": target_timestamp_iso, # Começa a busca a partir desta data/hora "format": "json", "formatversion": 2 # Formato JSON mais moderno e fácil de parsear } try: print(f"Consultando API MediaWiki para revisão de '{page_title}' em {target_date_str}...") response = requests.get(Wikipedia_Util.MEDIAWIKI_API_URL, params=params, headers=Wikipedia_Util.HEADERS, timeout=15) response.raise_for_status() data = response.json() # Verifica se a página foi encontrada page_data = data.get("query", {}).get("pages", []) if not page_data or page_data[0].get("missing", False): print(f"Página '{page_title}' não encontrada na API MediaWiki.") # Tenta verificar com a biblioteca wikipediaapi como fallback (pode pegar redirecionamentos) page = Wikipedia_Util.wiki_executor.page(page_title) if page.exists(): print(f"Página '{page_title}' existe (possivelmente redirecionada para '{page.title}'). Tentando novamente com o título canônico...") return Wikipedia_Util.get_wikipedia_revision_info(page.title, target_date_str) # Chama recursivamente com o título correto else: print(f"Página '{page_title}' realmente não encontrada.") return None, None # Extrai as revisões revisions = page_data[0].get("revisions", []) if not revisions: print(f"Nenhuma revisão encontrada para '{page_title}' antes ou em {target_date_str}.") # Pode acontecer se a página foi criada depois da data alvo return None, None revision = revisions[0] revid = revision.get("revid") timestamp = revision.get("timestamp") print(f"Encontrada revisão: ID={revid}, Timestamp={timestamp}") return revid, timestamp except requests.exceptions.RequestException as e: print(f"Erro ao chamar a API MediaWiki: {e}") return None, None except Exception as e: print(f"Erro ao processar resposta da API MediaWiki: {e}") return None, None @staticmethod def get_wikipedia_page_historical_content(page_title: str, target_date_str: str) -> List[Wikipedia_Historical_Page]: """Obtém o conteúdo Markdown de uma revisão histórica específica da Wikipedia.""" # Busca o ID da revisão correta usando a API MediaWiki revid, timestamp = Wikipedia_Util.get_wikipedia_revision_info(page_title, target_date_str) if not revid: print(f"Não foi possível encontrar uma revisão adequada para '{page_title}' em {target_date_str}.") return None # Constrói a URL para a revisão específica # Nota: Codifica o título da página para a URL # Precisamos garantir que estamos usando o título correto (pode ter sido redirecionado) page_check = Wikipedia_Util.wiki_executor.page(page_title) # Verifica novamente para obter o título canônico se houve redirecionamento if not page_check.exists(): print(f"Erro inesperado: Página '{page_title}' não encontrada após busca de revisão.") return None canonical_title = page_check.title encoded_title = urllib.parse.quote(canonical_title.replace(' ', '_')) revision_url = f"https://{Wikipedia_Util.WIKI_LANG}.wikipedia.org/w/index.php?title={encoded_title}&oldid={revid}" return Wikipedia_Historical_Page( title=canonical_title, url=revision_url, revision_id=str(revid), #parametro obrigatoriamente string timestamp=timestamp )