# -*- coding: utf8 -*-
# criado por LipeFontoura
import urllib
import datetime
import time
import math
import re
# dados de entrada
tamanho_total = 0
minimo_edicoes_mensais = 10
url_lista_usuarios = "http://pt.wiktionary.org/wiki/Wikcion%C3%A1rio:Lista_de_wikcionaristas_por_n%C3%BAmero_de_edi%C3%A7%C3%B5es"
# remover
img_aumento = u"<span style=\"color: #0c0; font-size: larger;\">▲</span>"
img_parado = u"[[Imagem:Straight Line Steady.svg|10px]]"
img_reducao = u"<span style=\"color: red; font-size: larger;\">▼</span>"
# obtem o dia atual
data_atual = datetime.datetime.utcnow()
str_data = data_atual.strftime("%d/%m/%Y")
# declara as constantes
usuario = 0
administrador = 1
burocrata = 2
total = 0
validas = 1
deletadas = 2
nomes_tipo = [u"Usuário", u"Administrador", u"Burocrata"]
prefixo = [u"",u"'''",u"'''"]
sufixo = [u"]]",u"]]'''",u" (###)]]'''"]
# funções de ordenação
primeiro = -1
igual = 0
segundo = 1
def ordenador_total(usuario1, usuario2) :
if (usuario1.edicoes[total] == usuario2.edicoes[total]) : return igual
if (usuario1.edicoes[total] > usuario2.edicoes[total]) : return primeiro
else: return segundo
def ordenador_validas(usuario1, usuario2) :
if (usuario1.edicoes[validas] == usuario2.edicoes[validas]) : return igual
if (usuario1.edicoes[validas] > usuario2.edicoes[validas]) : return primeiro
else: return segundo
def ordenador_primeira_edicao(usuario1, usuario2) :
if (usuario1.primeira_edicao.toordinal() == usuario2.primeira_edicao.toordinal()) : return igual
if (usuario1.primeira_edicao.toordinal() > usuario2.primeira_edicao.toordinal()) : return primeiro
else: return segundo
ordenadores = [ordenador_total, ordenador_validas, ordenador_primeira_edicao]
# declara os nomes dos meses
meses = {u"janeiro":1, u"fevereiro":2, u"março":3, u"abril":4, u"maio":5, u"junho":6, u"julho":7,
u"agosto":8, u"setembro":9, u"outubro":10, u"novembro":11, u"dezembro":12}
# funções com operações regulares
def re_prim(padrao, cadeia_caracteres) :
u"""Retorna a primeira correspondência de uma operação regular."""
resultado_re_prim = re.search(padrao, cadeia_caracteres, re.MULTILINE | re.DOTALL)
if (resultado_re_prim) : resultado_re_prim = resultado_re_prim.group()
return resultado_re_prim
def re_tudo(padrao, cadeia_caracteres) :
u"""Retorna uma lista com todas as correspondências de uma operação regular."""
return re.findall(padrao, cadeia_caracteres, re.MULTILINE | re.DOTALL)
# funções de data
def obter_data(string) : # [0-9][0-9]h[0-9][0-9]min de [0-9][0-9]? de [^ ]* de [0-9][0-9][0-9][0-9]
u"""Converte uma string com uma data num objeto de data."""
return datetime.datetime(year=int(re_prim(u"[0-9][0-9][0-9][0-9]", string)),
month=meses[re_prim(u"(?<=de )[^ ]*(?= de [0-9][0-9][0-9][0-9])", string)],
day=int(re_prim(u"(?<=min de )[0-9][0-9]?", string)),
hour=int(re.search(u"[0-9][0-9](?=h)", string).group()),
minute=int(re.search(u"[0-9][0-9](?=min)", string).group()))
# classe que conecta-se à internet
class Navegador(urllib.FancyURLopener) :
version = "Linux Mozilla"
urllib._urlopener = Navegador()
# comando que baixa o conteúdo de uma página
def baixar_pagina(nome) :
continuar = True
tentativas = 1
max_tentativas = 10
while continuar :
try :
acesso = urllib.urlopen(nome)
conteudo = acesso.read()
acesso.close()
continuar = False
except IOError :
print u"Houve um erro ao conectar-se a <" + nome + u">. Tentando novamente..."
tentativas += 1
if tentativas > max_tentativas : continuar = False
return unicode(str(conteudo), "UTF-8")
# classe que registra informações sobre um usuário
class Usuario :
def __init__(self, nome, link, tipo = usuario, observacao2 = None, observacao4 = None, observacao5 = None, observacao6 = None, posicao_anterior = -1, data_anterior = str_data) :
u"""Inicializa um novo usuário."""
self.nome = nome
self.link = link
self.observacao1 = None
self.observacao2 = observacao2
self.observacao4 = observacao4
self.observacao5 = observacao5
self.observacao6 = observacao6
self.tipo = tipo
self.edicoes = [0, 0, 0]
self.posicao_anterior = posicao_anterior
self.data_anterior = data_anterior
def carregar_dados(self) :
u"""Carrega dados sobre o usuário, como o total de edições, a sua atividade e sua data de registro."""
# verifica se o usuário está ativo
temp = baixar_pagina(u"http://pt.wiktionary.org/w/index.php?title=Especial:Contribui%C3%A7%C3%B5es&limit=" + unicode(minimo_edicoes_mensais) + "&target=" + self.link)
temp = re_tudo(u"(?<=\">)[0-2][0-9]h[0-5][0-9]min de [1-9][0-9]? de [^ ]* de [0-9][0-9][0-9][0-9](?=</a> \\(<a href\\=\"/w/index.php\\?title\\=)", temp)
mais_recente = obter_data(temp[0])
menos_recente = obter_data(temp[minimo_edicoes_mensais - 1])
del temp
diferenca_menos_recente = data_atual - menos_recente
diferenca_mais_recente = data_atual - mais_recente
if (diferenca_menos_recente.days > 31) :
self.observacao1 = u"(1)<ref>[[Usuário:" + self.nome + u"|" + self.nome + u"]] "
if (diferenca_mais_recente.days < 31) :
# o usuario esta inativo mas contribuiu ultimamente
dif_meses = int(math.floor(diferenca_menos_recente.days / 30))
if (dif_meses == 1) : str_meses = u"no último mês"
else :
dif_anos = int(math.floor(diferenca_menos_recente.days / 356))
dif_meses = int(math.floor((diferenca_menos_recente.days - 356*dif_anos) / 30))
if (dif_anos == 0) : str_meses = u"nos últimos " + unicode(dif_meses) + u" meses"
if (dif_anos == 1) :
str_meses = u"no último ano"
if (dif_meses == 1) : str_meses += u" e um mês"
if (dif_meses > 1) : str_meses += u" e " + unicode(dif_meses) + u" meses"
if (dif_anos > 1) :
str_meses = u"nos últimos " + unicode(dif_anos) + u" anos"
if (dif_meses == 1) : str_meses += u" e um mês"
if (dif_meses > 1) : str_meses += u" e " + unicode(dif_meses) + u" meses"
self.observacao1 += u"contribuiu pela última vez em " + unicode(mais_recente.strftime("%d/%m/%Y")) + u", mas não chegou a completar " + unicode(minimo_edicoes_mensais) + u" edições " + str_meses + u".</ref>"
else :
# o usuário está completamente inativo
self.observacao1 += u"não contribui desde " + unicode(mais_recente.strftime("%d/%m/%Y")) + u".</ref>"
else :
# o usuário está ativo
self.observacao1 = None
# verifica o total de edições do usuário
temp = baixar_pagina("http://tools.wikimedia.de/~interiot/cgi-bin/count_edits?user=" + self.link + "&dbname=ptwiktionary_p")
self.edicoes[validas] = int(re_prim("(?<=<tr><th>Total edits</th><td colspan\\='2'>)[1-9][0-9]*", temp))
self.edicoes[deletadas] = int(re_prim("(?<=<tr><th>Deleted edits</th><td colspan\\='2'>)[0-9]*", temp))
self.edicoes[total] = self.edicoes[validas] + self.edicoes[deletadas]
temp = re.search("(?<=<tr><th>First edit</th><td colspan='2'>)[0-9][0-9][0-9][0-9]/[0-9][0-9]/[0-9][0-9]", temp).group()
self.primeira_edicao = datetime.date(day = int(re_prim("(?<=[0-9][0-9][0-9][0-9]/[0-9][0-9]/)[0-9][0-9]", temp)),
month = int(re_prim("(?<=[0-9][0-9][0-9][0-9]/)[0-9][0-9](?=/[0-9][0-9])", temp)),
year = int(re_prim("[0-9][0-9][0-9][0-9](?=/[0-9][0-9]/[0-9][0-9])", temp)))
# cria a string com as observações
obs_string = ""
observacoes = [self.observacao1, self.observacao2, self.observacao4, self.observacao5, self.observacao6]
for observacao in observacoes :
if observacao :
if len(obs_string) > 0 : obs_string += u", "
obs_string += observacao
if len(obs_string) == 0 : obs_string = "-"
self.obs_string = obs_string
def imprimir(self, posicao) :
comparador = img_parado + u" <small>(0)</small>"
if (self.posicao_anterior == -1) : self.posicao_anterior = tamanho_total + 1
if (self.posicao_anterior) :
if (posicao < self.posicao_anterior) : comparador = img_aumento + u"<small> (+" + unicode(self.posicao_anterior - posicao) + ")</small>"
if (posicao > self.posicao_anterior) : comparador = img_reducao + u"<small> (–" + unicode(posicao - self.posicao_anterior) + ")</small>"
else :
comparador = img_aumento + u"<small> (+" + unicode(posicao) + ")</small>"
print u"| align=\"center\" | " + comparador
print u"| " + prefixo[self.tipo] + u"[[Usuário:" + self.nome + u"|" + self.nome + sufixo[self.tipo] + u" "
print "| " + str(self.edicoes[total]) + " <small>(" + str(self.edicoes[validas]) + " + " + str(self.edicoes[deletadas]) + ")</small>"
print "| " + self.primeira_edicao.strftime("%d/%m/%Y")
print "| [http://tools.wikimedia.de/~interiot/cgi-bin/count_edits?user=" + self.link + "&dbname=ptwiktionary_p " + str_data + "]"
print "| " + self.obs_string
print "|-"
# classe que salva os dados de usuários e marcadores
class Dados :
def __init__(self) :
self.usuarios = []
self.marcadores = []
def adicionar_marcador(self, marcador) :
self.marcadores.append(int(marcador))
def adicionar_usuario(self, usuario) :
self.usuarios.append(usuario)
# carrega os usuários e os marcadores a usar
def carregar_dados() :
dados = Dados()
# carrega a página com os usuários por número de edições
print u"Carregando lista de usuários e marcadores numéricos..."
conteudo = baixar_pagina(url_lista_usuarios)
# acha os estamentos com cada um dos usuário e com cada um dos marcadores
usuarios_html = re_tudo(u"<td align\\=\"center\">[1-9][0-9]*</td>.*?(?=</tr>)", conteudo)
marcadores_html = re_tudo(u"<td colspan\\=\"7\" align\\=\"center\"[^>]*><b>\\+[1-9][0-9]* edições</b></td>", conteudo)
# lê e interpreta os marcadores
for marcador_html in marcadores_html :
marcador = int(re_prim("(?<=<b>)\\+[1-9][0-9]*", marcador_html))
print u"Marcador " + unicode(marcador) + u" encontrado."
dados.adicionar_marcador(marcador)
# lê e interpreta os usuários
linhas_ocupadas_pela_posicao = 1
posicao_anterior = 1
# processa os usuários
for usuario_html in usuarios_html :
# separa o código HTML do usuário em linhas
str_linhas = re_tudo(u"<td[^>]*>.*?</td>", usuario_html)
soma = 1
if linhas_ocupadas_pela_posicao <= 1 :
linhas_ocupadas_pela_posicao = 1
posicao_anterior = int(re_prim("[1-9][0-9]*(?=</td>)", str_linhas[0]))
temp = re_prim(str_linhas[0], u"(?<=rowspan\\=)(\"[1-9][0-9]*\"|'[1-9][0-9]*'|[1-9][0-9]*)")
if temp : linhas_ocupadas_pela_posicao = int(re_prim(u"[1-9][0-9]*", temp))
else :
linhas_ocupadas_pela_posicao -= 1
soma = 0
# obtém o nome e o tipo do usuário
nome = re_prim(u"[^>]*(?= \\(###\\)</a></b>)", str_linhas[soma + 1])
if (nome) : tipo = burocrata
else :
nome = re_prim(u"[^>]*(?=</a></b>)", str_linhas[soma + 1])
if (nome) : tipo = administrador
else :
tipo = usuario
nome = re_prim(u"[^>]*(?=</a>)", str_linhas[soma + 1])
# procura o link e a data
link = re_prim("(?<=interiot/cgi-bin/count_edits\\?user\\=)[^&]*(?=\\&dbname=ptwiktionary_p)", str_linhas[soma + 4])
data_anterior = re_prim("(?<=rel\\=\"nofollow\">)[0-9][0-9]/[0-9][0-9]/[0-9][0-9][0-9][0-9](?=</a>)", str_linhas[soma + 4])
# obtém as observações sobre o usuário
observacao2 = re_prim(u"\\(2\\) [^<\\,]*", str_linhas[soma + 5])
observacao4 = re_prim(u"\\(4\\) [^<\\,]*", str_linhas[soma + 5])
observacao5 = re_prim(u"(?<=title\\=\").*?(?=\" rel\\=\"nofollow\">\\(5\\)</a>)", str_linhas[soma + 5])
observacao6 = re_prim(u"(?<=title\\=\").*?(?=\" rel\\=\"nofollow\">\\(6\\)</a>)", str_linhas[soma + 5])
if (observacao5) : observacao5 = u"[" + observacao5 + u" (5)]"
if (observacao6) : observacao6 = u"[" + observacao6 + u" (6)]"
print u"O usuário " + nome + u", que estava na posição " + unicode(posicao_anterior) + u" no dia " + data_anterior + u", foi encontrado."
dados.adicionar_usuario(Usuario(nome = nome,
link = link,
tipo = tipo,
observacao2 = observacao2,
observacao4 = observacao4,
observacao5 = observacao5,
observacao6 = observacao6,
posicao_anterior = posicao_anterior,
data_anterior = data_anterior))
return dados
# obtem a lista de usuarios
dados = carregar_dados()
tamanho_total = len(dados.usuarios)
print ""
print u"Começando a carregar os dados..."
for usuario in dados.usuarios :
usuario.carregar_dados()
str_tipo = u"Usuário "
if (usuario.tipo == administrador) : str_tipo = u"Administrador "
if (usuario.tipo == burocrata) : str_tipo = u"Burocrata "
print str_tipo + usuario.nome + u" carregado. Realizou " + unicode(usuario.edicoes[total]) + u" (" + unicode(usuario.edicoes[validas]) + u" + " + unicode(usuario.edicoes[deletadas]) + u") edições."
time.sleep(0.5)
usuarios = dados.usuarios
marcadores = dados.marcadores
marcadores.append(0)
indice = 1
while len(usuarios) > 0:
selecionados = usuarios
for ordenador in ordenadores :
selecionados_anterior = selecionados
selecionados = None
for usuario in selecionados_anterior :
if selecionados :
comparacao = ordenador(selecionados[0], usuario)
if (comparacao == igual) : selecionados.append(usuario)
if (comparacao == segundo) : selecionados = [usuario]
else : selecionados = [usuario]
# imprime o marcador
temp = selecionados[0].edicoes[total]
if (temp < marcadores[0]) :
while (temp < marcadores[0]) :
marcadores.remove(marcadores[0])
print u"| colspan=\"7\" align=\"center\" bgcolor=\"#dcdcdc\" | '''+" + unicode(marcadores[0]) + u" edições'''"
print "|-"
# imprime o número
if len(selecionados) == 1 : print "| align=\"center\" | " + str(indice)
else : print "| align=\"center\" rowspan\"" + str(len(selecionados)) + "\" | " + str(indice)
for selecionado in selecionados :
usuarios.remove(selecionado)
selecionado.imprimir(indice)
indice += len(selecionados)