ID | Descripción |
---|---|
P0405 | Viviendas Verticales |
P0406 | Viviendas urbanas en PCU U1 y U2 |
P0411 | Subsidios CONAVI |
In [2]:
descripciones = {
'P0405': 'Viviendas Verticales',
'P0406': 'Viviendas urbanas en PCU U1 y U2',
'P0411': 'Subsidios CONAVI'
}
In [92]:
# Librerias utilizadas
import pandas as pd
import sys
import urllib
import os
import csv
import zeep
import requests
from lxml import etree
import xmltodict
In [4]:
# Configuracion del sistema
print('Python {} on {}'.format(sys.version, sys.platform))
print('Pandas version: {}'.format(pd.__version__))
import platform; print('Running on {} {}'.format(platform.system(), platform.release()))
Los datos se descargan por medio de una conexión a un servicio SOAP proporcionado por el SNIIV. Para acceder a los datos proporcionados por cada uno de los servicios del SNIIV, tiene que hacerse un POST request, especificando en el encabezado el servicio al que se busca acceder y en el cuerpo de la petición, un XML con parametros para que el servidor de SNIIV pueda regresar una respuesta
In [85]:
# Esta celda contiene textos estándar para los encabezados y el cuerpo de la operación que se solicita al servidor.
# los textos entre corchetes {} sirven para especificar la operacion a la que se busca tener acceso
scheme = r'http://www.conavi.gob.mx:8080/WS_App_SNIIV.asmx?WSDL' #El scheme siempre es el mismo
SOAPAction = ('http://www.conavi.gob.mx:8080/WS_App_SNIIV/{}')
xmlbody = (
'<?xml version="1.0" encoding="utf-8"?>'
'<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">'
'<soap:Body>'
'<{} xmlns="http://www.conavi.gob.mx:8080/WS_App_SNIIV">'
'<dat></dat>'
'</{}>'
'</soap:Body>'
'</soap:Envelope>'
)
In [119]:
# Conexion y descarga de datos
operacion = 'Subsidios'
heads = {'Content-Type': 'text/xml; charset=utf-8',
'SOAPAction': SOAPAction.format(operacion)}
body = xmlbody.format(operacion, operacion)
r = requests.post(scheme, data=body, headers=heads)
print(r.content[0:300])
In [131]:
list(r.headers.keys())
Out[131]:
In [103]:
r = xmltodict.parse(r.content)
r.keys()
Out[103]:
In [114]:
# Después de parseada la respuesta a un diccionario de Python, los datos se encuentran varios niveles por debajo, por lo que es
# necesario explorar estos niveles hasta llegar a los datos útiles
rodict = r['soap:Envelope']['soap:Body']['{}Response'.format(operacion)]['{}Result'.format(operacion)]['app_sniiv_rep_subs']
rodict[0]
Out[114]:
In [116]:
# Con los datos parseados en forma de OrderedDict ya es posible hacer un DataFrame de la siguiente manera.
pd.DataFrame(rodict, columns=rodict[0].keys()).head()
Out[116]:
Lo anterior es un ejemplo de cómo pueden obtenerse datos desde el servicio montado por el SNIIV. Con base en este ejemplo es posible hacer una función que realice las peticiones de manera más compacta en cada caso.
In [144]:
def getsoap(operacion):
scheme = r'http://www.conavi.gob.mx:8080/WS_App_SNIIV.asmx?WSDL' #El scheme siempre es el mismo
SOAPAction = ('http://www.conavi.gob.mx:8080/WS_App_SNIIV/{}')
xmlbody = (
'<?xml version="1.0" encoding="utf-8"?>'
'<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">'
'<soap:Body>'
'<{} xmlns="http://www.conavi.gob.mx:8080/WS_App_SNIIV">'
'<dat></dat>'
'</{}>'
'</soap:Body>'
'</soap:Envelope>'
)
heads = {'Content-Type': 'text/xml; charset=utf-8',
'SOAPAction': SOAPAction.format(operacion)}
body = xmlbody.format(operacion, operacion)
r = requests.post(scheme, data=body, headers=heads)
if r.status_code != 200: #
print('status: {}\n**Operacion terminada**'.format(r.status_code))
return
else:
print('status: {}\nContent Type: {}'.format(r.status_code, r.headers['Content-Type']))
print('Date: {}\nContent Lenght: {}'.format(r.headers['Date'], r.headers['Content-Length']))
r = xmltodict.parse(r.content)
# return r
rodict = r['soap:Envelope']['soap:Body']['{}Response'.format(operacion)]['{}Result'.format(operacion)][list(test.keys())[0]]
return pd.DataFrame(rodict, columns=rodict[0].keys()).head()
In [145]:
test = getsoap('viv_vig_x_avnc')
In [156]:
Out[156]:
In [146]:
test
Out[146]: