Hola Visitante

Autor Tema: Accediendo a contenidos tras un formulario de autenticación  (Leído 444 veces)

Administación BDL

  • Administrator
  • *****
  • Mensajes: 66
    • Ver Perfil
Accediendo a contenidos tras un formulario de autenticación
« en: Agosto 09, 2015, 11:04:45 am »

Buenos días a todos,


Desde hace unos días estoy trabajando en la automatización de tareas repetitivas que consumen mucho tiempo. Una de las tareas era generar unos informes desde una máquina ACS de CISCO, esta máquina genera internamente el informe de usuarios conectados cada día a la red Wireless pero yo necesita obtener esos datos para introducirlos en un Excel. Por eso me puse en contacto con la gente de cisco pero sus ingenieros me contestaron que eso era una tarea imposible y que si lo quería tenía que cambiar el aparato entero.


Investigando un poco la web que generaba el informe vi que obtenía la información de la URL:


https://x.x.x.x/acsview/LoadTopNAuthenticationsPortlet.do?protocol=RADIUS&trend=ACS&timerange=LAST7DAYS&count=5&status=PASSED


donde x.x.x.x es la url del ACS.


Mi primera opción para descargarmelo fue usar C# con un HttpWebRequest pero al estar tras una página de login un poco extraña me fallaba ya que hacía varias redirecciones y no me guardaba las cookies correctamente entre la petición de login y la de descarga la información.


La segunda opción, también en C# fue usar el componente WebBrowser pero sin más… se me presentaron dos problemas:



  • En las versiones nuevas de IE no se pueden eliminar los cartelitos de advertencias de seguridad si el cert no es  válido

  • IE convierte el XML en HTML para darle formato, por lo que se obtienen los datos mezclados con tags HTML y JS


Advertencia SSL IE


Por suerte navegando por internet encontré un usuario que decía que para hacer un scrapping (minería de datos web) sencillo lo mejor era mechanize en python, así que decidí probarlo y la verdad es que me sorprendió lo rápido que pude alcanzar mi meta con esta librería. A continuación os explicaré el código utilizado:


Definición de imports y funciones utilizadas por el script para la creación de logs y paths:


import mechanize
import cookielib
import xml.etree.ElementTree as et
import xml.etree.cElementTree as et
import lxml.etree as et
import openpyxl
from openpyxl import load_workbook
from win32com import client
import win32com.client, types, pythoncom, sys, os, string
import getopt, os, sys, shutil,time
import ssl
import traceback
def cutit(s,n):
return s[n:]
def thisYear():
return str(time.strftime("%Y"))
def thisMonth():
return str(time.strftime("%m"))
def logError(errCode,msg):
f = open("C:\\LOGS\\"+os.path.basename(__file__).replace(".py",".txt"), 'w')
f.write(errCode+";"+str(msg).replace("\r\n","").replace("\n",""))
print str(msg)
f.close()
sys.exit(int(errCode))

La línea de código ssl._create_default_https_context = ssl._create_unverified_context permite saltarse la verificación de certs caducados y autofirmados que IE no permitía.



debug = False
ssl._create_default_https_context = ssl._create_unverified_context
try:
# Browser
br = mechanize.Browser()
# Cookie Jar
cj = cookielib.LWPCookieJar()
br.set_cookiejar(cj)
workbook_path="c:\\misinformes\\"
if not os.path.exists(workbook_path):
os.makedirs(workbook_path)
workbook_filename= "informe.xlsx"
workbook_new = "plantilla.xlsx"
ACS01="B"
ACS02="C"
# Browser options
br.set_handle_equiv(True)
br.set_handle_gzip(True)
br.set_handle_redirect(True)
br.set_handle_referer(True)
br.set_handle_robots(False)

# Follows refresh 0 but not hangs on refresh > 0
br.set_handle_refresh(mechanize._http.HTTPRefreshProcessor(), max_time=1)

En el código anterior se han creado la variable Browser de mechanize y se le ha asignado un contenedor de cookies, además de haber añadido las opciones de navegación de los headers



# Want debugging messages?
br.set_debug_http(debug)
br.set_debug_redirects(debug)
br.set_debug_responses(debug)
br.open('https://x.x.x.x/login.jsp')
# User-Agent (this is cheating, ok?)
br.addheaders = [('User-agent', 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.1) Gecko/2008071615 Fedora/3.0.1-1.fc9 Firefox/3.0.1')]

También se puede ver que está descargando en cada momento la librería mechanize y el como se maneja el user-agent. Del mismo modo se podrían añadir headers adicionales.


En el siguiente código viene la “chicha” del login, primero debemos seleccionar el nº de form que vamos a utilizar para logearnos, para saber el nº de form que se va ausar se pueden imprimir accediendo a la colección br.forms(), el siguiente paso es saber que campos componen el formulario. En este caso se me pedía el campo j_username y j_password. Una vez logeados, ya podemos descargarnos la información de la web que queramos del dispositivo. En este caso la web venía entre unos tags de script y unos div que mostraba una advertencia de flash. Por eso se trata la información recibida y se elimina.




for f in br.forms():
print f
br.select_form(nr=0)
br.form['j_username']='myAdmin'
br.form['j_password']='123456'
br.submit()
br.open('https://x.x.x.x/acsview/LoadTopNAuthenticationsPortlet.do?protocol=RADIUS&trend=ACS&timerange=LAST7DAYS&count=5&status=PASSED')
xmltext=br.response().read()
##Formateamos el XML quitamos comentarios y lineas en blanco
ind = xmltext.rfind('',0)
xmltext=cutit(xmltext, ind+11).replace("\r\n","").replace("\n","")[:-12]
print xmltext

Para finalizar tenemos el tratamiento de XML con python y la inserción dentro de un Excel. Además al finalizar el script mediante el propio excel convertimos xlsx a pdf mediante las interops de office.



tree = et.fromstring(xmltext)
filenames =[]
for row in tree.getchildren():
SnapDate = row.findall('SnapDate')[0]
print SnapDate.text
dates=SnapDate.text.split("/")
acs01 = row.findall('acs01')[0]
print acs01.text
acs02 = row.findall('acs02')[0]
print acs02.text
filename1=workbook_path+"20"+dates[2]+"."+dates[0]+" "+workbook_filename
print "filename:"+filename1+"\n"
if os.path.exists(filename1):
print "Opening:"+filename1+"\n"
wb = load_workbook(filename1)
else:
wb = load_workbook(workbook_path+workbook_new)
ws1 = wb.active
idx=str(int(dates[1])+2)
ws1[ACS02+idx]=int(acs02.text)
ws1[ACS01+idx]=int(acs01.text)
wb.save(filename = filename1)
if not filename1 in filenames:
filenames.append(filename1)
##Creacio dels PDF desde un EXCEL
for filename in filenames:
print "Creating pdf:"+filename.replace(".xlsx",".pdf")+"\n"
xlApp = win32com.client.Dispatch("Excel.Application")
books = xlApp.Workbooks.Open(filename)
ws = books.Worksheets[0]
ws.Visible = 1
ws.ExportAsFixedFormat(0, filename.replace(".xlsx",".pdf"))
xlApp.ActiveWorkbook.Saved = True
xlApp.ActiveWorkbook.Close
xlApp.Quit()
except Exception, e:
logError("-1",traceback.format_exc())
logError("0","OK")

Esta librería no os servirá en todos los casos ya que no permite ejecutar JS y hay que que utilizan JS para las autenticaciones,.. pero para tareas sencillas es más que suficiente.


Espero que este os haya sido de ayuda =).