Skip to content

Instantly share code, notes, and snippets.

@danilomac
Last active May 28, 2020 00:24
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save danilomac/ef81ba112429c77de056dceb73439f64 to your computer and use it in GitHub Desktop.
Save danilomac/ef81ba112429c77de056dceb73439f64 to your computer and use it in GitHub Desktop.
# -*- coding: utf-8 -*-
'''
@author: Danilo ([[Usuário:Danilo.mac]])
@licence: GNU Public Licence version 2 (GPLv2)
Script para avaliação automática de qualidade na Wikipédia lusófona, semelhante ao [[Módulo:Avaliação]]
Uso:
python qualidade.py <nome_do_arquivo>
O script lê o arquivo e interpreta cada linha como o título de um artigo, avalia a
qualidade e retorna o titulo com a qualidade.
Se o arquivo for um tsv, apenas a primeira coluna é interpretada como título e toda
linha é retornada com mais uma coluna com a qualidade
Opções:
-motivo Retorna o motivo da avaliação também
-revid Trata cada linha como o revision id da edição em vez de um título
-timestamp Trata a segunda linha do tsv como timestamp para avaliar a edição dessa data específica
'''
import re, json, sys, codecs
from urllib2 import urlopen
from urllib import quote
problemas = [u'artigo com problemas', u'artigo longo', u'artigo sobre direito com problemas', u'bsre', u'coi',
u'caracteres não-padrão', u'conflito interwiki', u'contextualizar2', u'conteúdo parcial', u'controverso',
u'corrigir', u'ctx2', u'curiosidades', u'direitos-autorais', u'disputa-bpv', u'divisão', u'em tradução',
u'expandir', u'expandir2', u'fusão', u'fusão com', u'fusão de', u'fusão vot', u'global', u'global/brasil',
u'global/lusofonia', u'global/portugal', u'hanzi', u'idioma estrangeiro', u'matrad', u'mtag', u'multitag',
u'má introdução', u'má tradução', u'não informado', u'não informado n', u'não-enc', u'não-enciclopédico',
u'não-enciclopédico2', u'parcial', u'parcialcontroverso', u'publicidade', u'rec', u'reciclagem',
u'reciclar-sobre', u'ren-pag', u'renomear página', u'revisão', u'revisão de tradução', u'revisão-sobre',
u's-fontes-bpv', u'sem cat', u'sem-fontes-bpv', u'sem-fontes-sobre', u'semimagem-arquitetura',
u'semimagem-sobre', u'separar', u'suspeito2', u'tradução de', u'vda2', u'wikificação']
bpd = re.compile(ur'(?<={{).+?(?=\||\n|}})') # busca predefinições
bp = re.compile(ur'(?:^|\n\n|==\n)[^*\n].{100,}?(?=\n\n|\n==)') # busca parágrafos
br = re.compile(ur'{{[Rr]efer[eê]ncias|{{[Rr]ef-?section|{{[Rr]odapé referências|==.*?[Rr]eferências.*?==|{{[Rr]eflist') # busca seção de referências
bl = re.compile(ur'\[\[[^:]*?\]\]') # busca ligações internas
bs = re.compile(ur'(?s)\n== ?([^=\n}{]+?) ?==(.+?)(?=\n==[^=\n]|$)') # busca seções
bss = re.compile(ur'\n===[^=\n]+?===\n') # busca subseções
bref = re.compile(ur'<ref[^\n/]*?>.*?</ref>|<ref .+?/>', re.I|re.S) # busca notas de rodapé/referências
brefname = re.compile(ur'(?<=<ref name=).+?(?= />|/>| >|>)', re.I)
bi = re.compile(ur'\[\[(ficheiro|imagem?|file|arquivo):.*?(\||\]\])|{{imagem dupla\||\| ?imagem *=.*?\.[a-z]{3,4}', re.I) # busca imagens
excecoes = [u'Referências', u'Ver também', u'Notas', u'Notas e referências', u'Discografia', u'Galeria de imagens',
u'Referências gerais', u'Leitura adicional', u'Subdivisões', u'Leitura recomendada', u'Ligações externas', u'Bibliografia'] #exeções para seções
def avaliar(pagename, timestamp=False):
if timestamp:
pagename = quote(pagename.encode('utf-8'), safe='')
api = urlopen('https://pt.wikipedia.org/w/api.php?action=query&format=json&prop=revisions&titles=%s&rvprop=content&rvstart=%d&rvlimit=1' % (pagename, int(timestamp)))
elif re.match(r'r\d+', pagename):
api = urlopen('https://pt.wikipedia.org/w/api.php?action=query&format=json&prop=revisions&revids=%d&rvprop=content&rvlimit=1' % int(pagename[1:]))
else:
pagename = quote(pagename.encode('utf-8'), safe='')
api = urlopen('https://pt.wikipedia.org/w/api.php?action=query&format=json&prop=revisions&titles=%s&rvprop=content&rvlimit=1' % pagename)
try:
texto = json.loads(api.read())['query']['pages'].values()[0]['revisions'][0]['*']
except:
return ('?', u'página não existe')
if len(texto) < 2000:
return (1, u'menos de 2000 bytes')
predefs = dict([(p.lower(), p) for p in bpd.findall(texto)])
if u'artigo destacado' in predefs:
return (6, u'artigo destacado')
if u'artigo bom' in predefs:
return (5, u'artigo bom')
ref = br.search(texto)
if not ref and len(texto) < 8000:
return (1, u'menos de 8000 bytes e não tem referências')
paragrafos = bp.findall(bref.sub('', texto))
wkf = [x for x in paragrafos if len(x) > 2504]
if wkf:
return (1, u'parágrafo muito grande (%d bytes): "%s..."' % (len(wkf[0]), wkf[0][0:23]))
wikilinks = bl.findall(texto)
if len(wikilinks) < 10:
return (1, u'menos de 10 ligações internas')
subp = filter(lambda x:x.find(u'. ') == -1, paragrafos)
if len(paragrafos) - (len(subp)/2) < 5:
return (1, u'menos de 5 parágrafos')
# Verificando parâmetros para qualidade 3:
secoes = bs.findall(texto)
subsec = bss.findall(texto)
#if len(secoes) + (len(subsec)/5) < 2: return (1, u'menos de 2 seções')
for predef in [u'mínimo', u'contexto', u'reciclagem', u'reciclar-sobre']:
if predef in predefs:
return (1, u'encontrado [[predefinição:%s]]' % predefs[predef])
if not ref:
return (2, u'não tem seção de referências')
if len(texto) < 12000:
return (2, u'menos de 12000 bytes')
if len(wikilinks) < 30:
return (2, u'menos de 30 ligações internas')
if len(secoes) + (len(subsec)/5) < 3:
return (2, u'menos de 3 seções')
refs = bref.findall(texto)
refnames = brefname.findall(texto)
nrefs = len(refs) - len(refnames) + len(set(refnames))
if nrefs < 5:
return (2, u'menos de 5 referências')
imagens = bi.findall(texto)
if len(imagens) < 1:
return (2, u'não tem imagem')
for predef in [u'esboço', u'wikificação', u'revisão', u'revisão-sobre']:
if predef in predefs: return (2, u'encontrado [[predefinição:%s]]' % predefs[predef])
# Verificando parâmetros para qualidade 4:
if len(texto) < 20000:
return (3, u'menos de 20000 bytes')
if len(wikilinks) < 50:
return (3, u'menos de 50 ligações internas')
if len(secoes) + (len(subsec)/5) < 5:
return (3, u'menos de 5 seções')
if nrefs < 10:
return (3, u'menos de 10 referências')
if len(imagens) < 2:
return (3, u'só tem uma imagem')
for predef in problemas:
if predef in predefs:
return (3, u'encontrado [[predefinição:%s]]' % predefs[predef])
for s in secoes:
if s[0] not in excecoes:
if not bref.search(s[1]) and len(bp.findall(s[1])) > 1:
return (3, u'não foram encontradas referências na seção "%s"' % s[0])
# Nada encontrado:
return (4, u'indique para [[WP:EAD|EAD]] quando o artigo satisfizer os [[Wikipédia:O que é um artigo bom?|critérios de artigo bom]]')
if __name__ == '__main__':
args = sys.argv[1:]
mot = '-motivo' in args
revid = '-revid' in args
timestamp = '-timestamp' in args
arquivo = args[-1]
with codecs.open(arquivo, 'r', 'utf-8') as f:
for line in f:
line = line.strip('\r\n')
page = line.split('\t')
q = avaliar((revid and u'r' or u'') + page[0], timestamp and page[1])
if mot:
print '%s\t%d\t%s' % (line, q[0], q[1])
else:
print '%s\t%s' % (line, q[0])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment