Usuario:Chixpy/PyWikipediaBot/estadisticas.py

De Inciclopedia
Ir a la navegación Ir a la búsqueda
#!/usr/bin/python
# -*- coding: utf-8  -*-

#Un intento cutre para conseguir las estadísticas de las páginas, debería funcionar para cualquier familia

#Todo está manual porque hay que hacerlo a través de api.php y Special:Statistics?action=raw
#pyWikipediabot lo hace a través de las páginas y wikia tiene el límite hasta 1000 en la página de [[special:longpages]]
#La verdad es que para lo único que uso Pywikipediabot es para obtener el listado de lenguajes y escribir en la página

#Para páginas largas: http://inciclopedia.wikia.com/api.php?action=query&list=allpages&aplimit=500&apminsize=1000&format=phpfm
#php es la forma más compacta (phpfm para verlo en el explorador), lo hace de 500 en 500 porque solo los sysops pueden 5000

#ATENCION: USO EXCESIVO DE BLOQUES TRY...EXCEPT XD XD XD XD XD XD

from __future__ import division
import re
import codecs
import wikipedia
from urllib import urlopen, quote

OtrasWikis = {
  "Inciclopedia": ["es", "inciclopedia.wikia.com", "/index.php", "/api.php"],
  "Frikipedia": ["fk", "www.frikipedia.es", "/index.php", "/api.php"],
#  "Wikipediars": ["wprs", "www.wikipediars.com", "/index.php", "/api.php"],
}

class BasicBot:
  def __init__(self):
    self.TotalArticulos = 0
    self.TotalFicheros = 0
    self.TotalPaginas = 0
    self.TotalEdiciones = 0
    self.TotalUsuarios = 0
    self.TotalActivos = 0
    self.TotalAdministradores = 0
    self.ArticulosActual = 0 # Para guardar temporalmente el número de artículos de la wiki que estamos recorriendo
    self.AnadirOtrasWikis = True

    self.site = wikipedia.getSite()
    self.texto = ""

  def run(self):
    # Pone el sumario
    wikipedia.setAction(u"Actualizando estadísticas")
    self.treat()

  def _EscribirCabecera(self):
    self.texto += u"{| {{tablabonita|alineación=col1cen|text-align:right; font-size: 90%;}}\n"
    self.texto += u"|-\n!|Leng<br />\n!|Edic<br />\n!|Pág<br />\n!|Ed/Pg<br />\n!|Art<br />\n!|%<br />\n!|Fich<br />\n"
    self.texto += u"!|Fch/Art<br />\n!|Usu<br />\n!|Act<br />\n!|Adm<br />\n"
    self.texto += u"!|>64k<br />\n!|%<br />\n!|>32kb<br />\n!|%<br />\n!|>16kb<br />\n!|%<br />\n"
    self.texto += u"!|>8k<br />\n!|%<br />\n!|>4kb<br />\n!|%<br />\n"    

  def _EscribirTotales(self):
    self.texto += u"\n{| {{tablabonita|alineación=|text-align: center;}}\n"
    self.texto += u"|-\n!|Lenguaje\n!|Ediciones\n!|Páginas\n!|Artículos\n!|Ficheros\n!|Usuarios\n!|Activos\n!|Administradores\n"
    self.texto += u"|-\n||TOTAL\n"
    self.texto += u"||%d\n" % (self.TotalEdiciones)
    self.texto += u"||%d\n" % (self.TotalPaginas)
    self.texto += u"||%d\n" % (self.TotalArticulos)
    self.texto += u"||%d\n" % (self.TotalFicheros)
    self.texto += u"||%d\n" % (self.TotalUsuarios)
    self.texto += u"||%d\n" % (self.TotalActivos)
    self.texto += u"||%d\n" % (self.TotalAdministradores)
    self.texto +=  u"|}\n----\n"

  def _LeerEstadisticas(self, URLBase, Path):
    # Expresiones regulares para extraer los datos
    # Expresion1 incluye "activesers" mientras que Expresion2 no
    # He hecho un montón de pruebas para unirlas poniendo (?:activeusers=(?P<activeusers>.*);)? pero no rula
    Expresion1 = r"total=(?P<total>.*);good=(?P<good>.*);views=(?P<views>.*);edits=(?P<edits>.*);users=(?P<users>.*);activeusers=(?P<activeusers>.*);admins=(?P<admins>.*);images=(?P<images>.*);jobs=(?P<jobs>.*)"
    Expresion2 = r"total=(?P<total>.*);good=(?P<good>.*);views=(?P<views>.*);edits=(?P<edits>.*);users=(?P<users>.*);admins=(?P<admins>.*);images=(?P<images>.*);jobs=(?P<jobs>.*)"

    try:
      Estadisticas = urlopen(u'http://%s%s?title=Special:Statistics&action=raw' %                             
                           (URLBase, Path)).read()
    except:
      return False
    
    wikipedia.output(Estadisticas)

    # Probamos con Expresion1 (con Activeusers)
    param = re.search(Expresion1, Estadisticas)
    try:
      Articulos = int(param.group('good'))
    except: # Probamos sin activeusers
      param = re.search(Expresion2, Estadisticas)
      try:
        Articulos = int(param.group('good'))
      except: # Ops, algo falló
        return False

    self.ArticulosActual = Articulos
    Ediciones = int(param.group('edits'))
    Paginas = int(param.group('total'))
    Ficheros = int(param.group('images'))
    Admin = int(param.group('admins'))
    Usuarios = int(param.group('users'))

    try:
      Activos = int(param.group('activeusers'))
    except:
      Activos = 0

    # Escribimos los datos
    self.texto += u"||%d\n" % (Ediciones)
    self.texto += u"||%d\n" % (Paginas)
    temp = u"||%3.2f\n" % (Ediciones / Paginas)
    self.texto += temp.replace(".", ",")
    self.texto += u"||%d\n" % (Articulos)
    temp = u"||%3.2f\n" % (Articulos * 100 / Paginas)
    self.texto += temp.replace(".", ",")
    self.texto += u"||%d\n" % (Ficheros)
    temp = u"||%3.2f\n" % (Ficheros / Articulos)
    self.texto += temp.replace(".", ",")
    self.texto += u"||%d\n" % (Usuarios)
    self.texto += u"||%d\n" % (Activos)
    self.texto += u"||%d\n" % (Admin)

    # Actualizamos acumuladores
    self.TotalArticulos += Articulos
    self.TotalFicheros  += Ficheros
    self.TotalPaginas   += Paginas
    self.TotalEdiciones += Ediciones
    self.TotalUsuarios  += Usuarios
    self.TotalActivos   += Activos
    self.TotalAdministradores += Admin    

    return True

  def _LeerPaginasLargas(self, URLBase, APIPath):
    # Un poco cutre hacerlo de esta forma...
    # Habría que mejorarlo mucho
    Expresion1 = r"\"apfrom\";s:[0-9]*:\"(?P<sig>.*)\";\}\}"
    Expresion2 = r"\"allpages\";a:(?P<paginas>.*):\{[i\}]"    

    for i in [65535, 32767, 16383, 8191, 4095]:
#    for i in [8191]:
      wikipedia.output(u"Buscando páginas de más de %d bytes" % i)
      Contador = 0
      try:
        Estadisticas = urlopen(u'http://%s%s?action=query&list=allpages&aplimit=500&apminsize=%d&format=php' %                             
                           (URLBase, APIPath, i)).read()        
      except:
        return False

      Fin = False
      while not Fin:        
        param = re.search(Expresion1, Estadisticas)
        try:
          Siguiente = quote(param.group(u"sig"))
          wikipedia.output(u"Leido hasta: %s" % Siguiente)
          try:
            Estadisticas = urlopen(u'http://%s%s?action=query&list=allpages&aplimit=500&apminsize=%d&format=php&apfrom=%s' %                             
                           (URLBase, APIPath, i, Siguiente)).read()
          except:
            return False          
          Contador += 500
        except:
          try:
            param = re.search(Expresion2, Estadisticas)
            Contador += int(param.group(u"paginas"))
          except:
            return False
          Fin = True

      self.texto += u"||%d\n" % (Contador)
      temp = u"||%3.2f\n" % (Contador * 100 / self.ArticulosActual )
      self.texto += temp.replace(".", ",")      
      wikipedia.output(u"--> %d páginas encontradas" % Contador);
    return True
  

  def treat(self):
    self._EscribirCabecera()
    
    # Datos de las wikis Uncyclopedia
    for i in self.site.languages():
#    for i in ["es"]:
      self.ArticulosActual = 0
      wikipedia.output(u"\n>>> \03{yellow}%s\03{default} - \03{lightpurple}%s\03{default} <<<" %
                       (i, self.site.family.langs[i]))
      wikipedia.output(u'http://%s%s?title=Special:Statistics&action=raw' %
                       (self.site.family.langs[i], self.site.family.path(i)))
 
      # Nueva fila para la wiki
      self.texto += u"|-\n||[[:%s:]]\n" % i
      
      if not self._LeerEstadisticas(self.site.family.langs[i], self.site.family.path(i)):
        self.texto += u"||\n||\n||\n||\n||\n||\n||\n||\n||\n||\n||\n||\n||\n||\n||\n||\n||\n||\n||\n||\n" #Fila vacía
        wikipedia.output(u'ERROR -> Al acceder a [[special:Statistics]]')
        continue

      if not self._LeerPaginasLargas(self.site.family.langs[i], self.site.family.apipath(i)):
#        self.texto += u"||\n||\n||\n||\n||\n||\n||\n||\n||\n||\n" #Fila vacía
        wikipedia.output(u'ERROR -> Al acceder al API')

    #Cerramos tabla
    self.texto += u"\n|}\n"
    
    # Escribimos los totales
    self._EscribirTotales()
    
    # Ahora lo hacemos con las wikis listadas al principio
    if self.AnadirOtrasWikis:
      self.TotalArticulos = 0
      self.TotalFicheros = 0
      self.TotalPaginas = 0
      self.TotalEdiciones = 0
      self.TotalUsuarios = 0
      self.TotalActivos = 0
      self.TotalAdministradores = 0
      self.ArticulosActual = 0

      self._EscribirCabecera()

      for i in OtrasWikis:
        self.ArticulosActual = 0
        wikipedia.output(u"\n>>> \03{yellow}%s\03{default} - \03{lightpurple}%s\03{default} <<<" %
                         (i, OtrasWikis[i][1]))
        wikipedia.output(u'http://%s%s?title=Special:Statistics&action=raw' %
                         (OtrasWikis[i][1], OtrasWikis[i][2]))
 
        # Nueva fila para la wiki
        self.texto += u"|-\n||[[%s|%s]]\n" % (i, OtrasWikis[i][0])
      
        if not self._LeerEstadisticas(OtrasWikis[i][1], OtrasWikis[i][2]):
          self.texto += u"||\n||\n||\n||\n||\n||\n||\n||\n||\n||\n||\n||\n||\n||\n||\n||\n||\n||\n||\n||\n" #Fila vacía
          wikipedia.output(u'ERROR -> Al acceder a [[special:Statistics]]')
          continue

        if not self._LeerPaginasLargas(OtrasWikis[i][1], OtrasWikis[i][3]):
#          self.texto += u"||\n||\n||\n||\n||\n||\n||\n||\n||\n||\n" #Fila vacía
          wikipedia.output(u'ERROR -> Al acceder al API')    


      self.texto +=  u"|}\n"
    
      self._EscribirTotales()
    
    self.texto +=  u"===Leyenda===\n"
    self.texto +=  u";Leng\n"
    self.texto +=  u":Lenguaje de la wiki\n"
    self.texto +=  u";Edic\n"
    self.texto +=  u":Número total de ediciones\n"
    self.texto +=  u";Pág\n"
    self.texto +=  u":Número total de páginas creadas\n"
    self.texto +=  u";Ed/Pg\n"
    self.texto +=  u":Ediciones por página\n"
    self.texto +=  u";Art\n"
    self.texto +=  u":Número de artículos (En el espacio principal, con un enlace y no se que otra restricción)\n"
    self.texto +=  u";%\n"
    self.texto +=  u":Porcentaje de artículos sobre el total de páginas\n"
    self.texto +=  u";Fich\n"
    self.texto +=  u":Número de ficheros (imágenes, sonidos, etc) subidos a la wiki\n"
    self.texto +=  u";Fch/Art\n"
    self.texto +=  u":Número de ficheros por artículos (es decir, más o menos el número de imágenes en cada artículo)\n"
    self.texto +=  u";Usu\n"
    self.texto +=  u":Número de usuarios\n"
    self.texto +=  u";Act\n"
    self.texto +=  u":Número de usuarios activos (-1 es que tienen desactivado algo seguramente)\n"
    self.texto +=  u";Adm\n"
    self.texto +=  u":Número de administradores\n"
    self.texto +=  u";>64kb, %\n"
    self.texto +=  u":Artículos de más de 64kb y su porcentaje sobre el total\n"
    self.texto +=  u";>32kb, %\n"
    self.texto +=  u":Artículos de más de 32kb y su porcentaje sobre el total\n"
    self.texto +=  u";>16kb, %\n"
    self.texto +=  u":Artículos de más de 16kb y su porcentaje sobre el total\n"
    self.texto +=  u";>8k, %\n"
    self.texto +=  u":Artículos de más de 8kb y su porcentaje sobre el total\n"
    self.texto +=  u";>4kb, %\n"
    self.texto +=  u":Artículos de más de 4kb y su porcentaje sobre el total\n"
    self.texto +=  u"===Notas===\n"
    self.texto +=  u"La tabla ya no la hago a mano, he hecho un bot con el pywikipediabot. "
    self.texto +=  u"Así me evito tener que estar haciéndolo a mano y las posibles fallos que puda tener\n\n"

    self.texto +=  u"El kB está comparado como lo es informáticamente, es decir: 65.536B, 32.768B, 16.384B,"
    self.texto +=  u"8.192B y 4096B respectivamente.\n\n"

    self.texto += u"Las que no tienen nada de nada... Será que está mal configurada en el bot o "
    self.texto += u"que ha dado error al intentar acceder\n\n"

    self.texto +=  u"Aquellas en las que no se tienen los tamaños de los artículos s que no tienen activado"
    self.texto +=  u"el api.php (Tiene que escribir <code><nowiki>$wgEnableAPI=true;<" + "/nowiki><code> en "
    self.texto +=  u"LocalSettings.php y solo lo pueden hacer quien tenga acceso al servidor donde esté instalada\n\n"

    self.texto +=  u";Para las de Wikia\n"
    self.texto +=  u"*El número de usuarios son el total de toda Wikia\n"    

    fichero = codecs.open('salida.txt', mode='w', errors='strict', encoding='utf-8',  buffering=1)
    fichero.write(self.texto)
    fichero.close    

    page=wikipedia.Page(self.site, u"User:Chixpy/Estadistitis")
    try:
      page.put(self.texto, minorEdit = False)
    except wikipedia.LockedPage:
      wikipedia.output(u"Página bloqueada: %s" % page.aslink())
    except wikipedia.EditConflict:
      wikipedia.output(u'Conflicto de edición: %s' % (page.title()))
    except wikipedia.SpamfilterError, error:
      wikipedia.output(u'Puto filtro anti-spam: %s - %s' % (page.title(), error.url))

def main():
  bot = BasicBot()
  bot.run()

if __name__ == "__main__":
  try:
    main()
  finally:
    wikipedia.stopme()