Escribiendo el Grafo de Materias de mi Carrera
Fecha: December 14th, 2009 | Categoría: Informatica | 4 Comments »Bueno, como paso previo a lanzar mi aplicación para navegar IOL (la plataforma para los contenidos de mi universidad) de manera decente (JIOLSucker no me cabe), me puse a investigar cómo navegar con python una página web.
Lo primero que me entretuvo fue ver cómo se hacen estas cosas en python, cómo existen dos librerías que se llaman igual y son necesarias (urllib vs urllib2), cómo armar una request; etcétera.
Revisé el código de IOL2Twitter que publicaron los capos de Zauber (muy buena empresa Argentina de software… hacen muy buenos laburos), pero era sólo para las noticias (y las mismas no necesitaban login). Así que seguí metiendo mano a ver cómo era para loguearse en IOL.
Resulta que hay que poner un número mágico como hidden value en el form… el primer WTF. También se pasa el “comando” a la página que controla todo por hidden value del form.
Con estas líneas de código ya estaba logueado en IOL:
-
import urllib, urllib2
-
-
opener = urllib2.build_opener(urllib2.HTTPCookieProcessor())
-
urllib2.install_opener(opener)
-
-
domain = ‘http://iol.itba.edu.ar/itbaV/’
-
-
entrada_request = urllib2.Request(domain+‘mynav.asp’, urllib.urlencode({‘txtdni’:‘34654754′, ‘txtpwd’:‘PASS’, ’secretNr’:‘894268381′, ‘cmd’:‘login’}), {‘Referer’:domain})
Empecé parseando la lista de materias activas de la navigation bar:
-
html_data = ""
-
entrada = urllib2.urlopen(entrada_request)
-
for linea in entrada.readlines():
-
html_data += linea
-
-
lista_materias = []
-
while html_data:
-
donde = html_data.find(‘mynav.asp?cmd=ChangeContext&nivel=4′)
-
if donde == -1:
-
html_data = None
-
else:
-
numero = html_data[donde+51:donde+56]
-
nombre = html_data[donde+77: donde+77+html_data[donde+77:].find(‘\n‘)]
-
lista_materias.append((numero, nombre))
-
html_data = html_data[donde+77+html_data[donde+77].find(‘\n‘):]
Después, entrando en el analítico de notas, saqué la lista de materias de la carrera e info acerca de en qué cuatrimestre se hace cada materia:
-
materias = []
-
descriptor = ""
-
while html_data:
-
donde = html_data.find(‘CodMat">’)
-
if donde == -1:
-
html_data = None
-
else:
-
descarte = html_data[:donde]
-
if descarte.find(‘class="cuatrimestre"’) != -1:
-
descarte = descarte[descarte.find(‘class="cuatrimestre"’)+21:]
-
descriptor = descarte[:descarte.find(‘<’)]
-
numero = html_data[donde+8:donde+13]
-
donde = html_data.find(‘MatDesc">’)
-
nombre = html_data[donde+9:donde+9+html_data[donde+9:].find(‘<’)]
-
materias.append((numero, nombre, descriptor))
-
html_data = html_data[donde+20:]
Funcioncita para ver cuales son las correlatividades de cada materia:
-
def correlativas(codigo):
-
urllib2.urlopen(domain + "mynav.asp?cmd=ChangeContext&nivel=4&snivel=" + codigo)
-
pagina = urllib2.urlopen(domain+‘materias/materia2.asp?nivel=4&snivel=’+codigo)
-
html = ""
-
for line in pagina.readlines():
-
html += line
-
lista = []
-
while html:
-
donde = html.find(‘ChangeContext&nivel=4′)
-
if donde == -1:
-
html = None
-
else:
-
lista.append(html[donde+29:donde+34])
-
html = html[donde+35:]
-
return list(set(lista))
Por último, me escribí un “.dot” para dibujar el grafo de correlatividades
-
C = {}
-
for ma in materias:
-
C[ma[0]] = correlativas(ma[0])
-
out = "digraph materias {\n"
-
cuatris = list(set([e[2] for e in materias]))
-
for a in cuatris:
-
cosas = list(set([b[1] for b in materias if b[2] == a]))
-
out += "\t{rank=same; "
-
for c in cosas:
-
out += " \"" + c + "\"; "
-
out += "}\n"
-
-
corr = ""
-
-
for ma in materias:
-
desde = C[ma[0]]
-
desde = [ a[1] for a in materias if a[0] in desde ]
-
for a in desde:
-
corr += "\t\"" + a + "\" -> \"" + ma[1] + "\";\n"
-
-
archivo = open("output.txt", ‘w’)
-
archivo.write(out)
-
archivo.write(corr)
-
archivo.write("}\n")
-
archivo.close()
Acá hay un png exportado de cómo quedó (no me gustó, es todo feo…)
Código para descargar: iolparser.py (zipeado)

te recomiendo que uses Beautiful Soup, un parser de HTML/XML en python:
http://www.crummy.com/software/BeautifulSoup/
en vez de esos horribles find y numeros mágicos, que dependen de que no cambie ni un sólo caracter del HTML…
(si es que querés pasar de la etapa experimental)
(a lo cual te insto, a ver si logramos algo usable de IOL)
(es más si hacés un svn de un proyecto en python para hacer eso te ayudo codeando)
abrazo
Manu
Que raro. Justamente anoche se me ocurrió hacer un árbol de correlatividades.
Me ahorraste el laburo. ¡Gracias! Ahora puedo ver en que me anoto.
El numero magico aparecio como “challenge” para intentar romper el login de jiol (que tambien era usado desde apuntesitba para autenticar a sus usuarios).
http://juan.zauber.com.ar/2008/5/26/iolsucker-3-15
Me imagino que son mas pythonero que javeros; pero desde hace rato jiol provee un API para las acciones que si requieren login (obtener archivos; etc; ej: https://svn.leak.com.ar/jiol/trunk/api/src/main/java/ar/com/leak/iolsucker/model/IolDAO.java)
Un poco de background en:
http://juan.zauber.com.ar/2009/8/15/release-jiolsucker-3-16 No tiene tanto movimiento el proyecto (porque no uso tanto iol); pero siempre alguien que lo use para algo es bienvenido.
iol2twitter es trabajo en progreso relacionado con el proyecto http://labs.zauber.com.ar/twitterbots/ y un poco de http://www.slideshare.net/zaubersoftware/barcamp-buenos-aires-linkeddata-mashups-30)