Final_Assignment_Template / wikipedia_util.py
gdms's picture
Montagem arquitetura
30944a6
raw
history blame
6.08 kB
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 ([email protected])'
}
wiki_executor = wikipediaapi.Wikipedia(
language=WIKI_LANG,
extract_format=wikipediaapi.ExtractFormat.HTML, # Usado apenas para page.exists()
user_agent='MyCoolSearchBot/1.0 ([email protected])' # 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
)