Last active
August 29, 2015 13:55
-
-
Save mekler/8753820 to your computer and use it in GitHub Desktop.
Scrapper para descargar la información del Censo Educativo 2013
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# coding=utf-8 | |
import pycurl | |
import StringIO | |
import sys | |
import ast | |
import pymongo | |
from pymongo import MongoClient | |
def construyeSQL(cadena): | |
aux = cadena.split(' ') | |
if len(aux)>1: | |
response = '"' | |
for i in range(len(aux)-1): | |
response = response + 'CONTAINS( [C_BUSQUEDA], \'FORMSOF(Inflectional,'+aux[i]+')\' ) AND ' | |
response = response + 'CONTAINS( [C_BUSQUEDA], \'FORMSOF(Inflectional,'+aux[i+1]+')\' ) "' | |
else: | |
if len(aux)==1: | |
response = '"CONTAINS( [C_BUSQUEDA], \'FORMSOF(Inflectional,'+cadena+')\' ) "' | |
return response | |
def pideCenso(post_data,method): | |
url = 'http://cemabe-preliminares.inegi.org.mx/ajaxpro/CEMABE_preliminares.CEscuelas,CEMABE_preliminares.ashx' | |
post_vars_length = 'Content-Length: ' + str(len(post_data)) | |
method_header = 'X-AjaxPro-Method: '+ method | |
c = pycurl.Curl() | |
c.setopt(pycurl.URL, url) | |
c.setopt(pycurl.HTTPHEADER, ['Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8','Accept-Language: en-US,en;q=0.5','Cache-Control: no-cache','Connection: keep-alive','Content-Type: text/plain; charset=utf-8','Host: cemabe-preliminares.inegi.org.mx','Pragma: no-cache','Referer: http://cemabe-preliminares.inegi.org.mx/','User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:26.0) Gecko/20100101 Firefox/26.0',method_header, post_vars_length ]) | |
c.setopt(c.POSTFIELDS, post_data) | |
import StringIO | |
b = StringIO.StringIO() | |
c.setopt(pycurl.WRITEFUNCTION, b.write) | |
try: | |
c.perform() | |
response_string = b.getvalue() | |
response = ast.literal_eval(response_string[:-3]) | |
b.close() | |
except: | |
response = ['error'] | |
client = MongoClient() | |
db = client.censo_2013 | |
posts = db.errores | |
post={ | |
'post_data':post_data, | |
'method':method | |
} | |
posts.insert(post) | |
return response | |
estados = ['aguascalientes','baja california','baja california sur', 'campeche','coahuila','colima','chiapas','chihuahua','distrito federal','durango','guanajuato','guerrero','hidalgo','jalisco','mexico','michoacan','morelos','nayarit','nuevo leon','oaxaca','puebla','queretaro','san luis potosi','sinaloa','sonora','tabasco','tamaulipas','tlaxcala','veracruz','yucatan','zacatecas'] | |
#estados = ['baja california sur', 'campeche','coahuila','colima','chiapas','chihuahua','distrito federal','durango','guanajuato','guerrero','hidalgo','jalisco','mexico','michoacan','morelos','nayarit','nuevo leon','oaxaca','puebla','queretaro','quintana roo','san luis potosi','sinaloa','sonora','tabasco','tamaulipas','tlaxcala','veracruz','yucatan','zacatecas'] | |
#response[0] -> KML | |
#response[1] -> string estructurado por parte del inegi. info parecida al kml mas datos generales | |
#response[2],response[3] -> lat, long de la ciudad | |
#response[4] -> numero de registros regresados | |
#response[5] -> total de registros | |
#response[6] -> ultimo registro regresado | |
for estado in estados: | |
sql = construyeSQL(estado) | |
base = pideCenso('{"query":'+sql+',"vent":null,"r_ini":"0","r_fin":"50"}','BusqCT') | |
if base[0]!='error': | |
total_registros = int(base[5]) | |
else: | |
total_registros = 0 | |
ini = 0 | |
fin = 50 | |
client = MongoClient() | |
db = client.censo_2013 | |
posts = db.cemabe_2 | |
kmls = db.cemabe_kmls_2 | |
i=0 | |
while ini<total_registros: | |
print ini,fin | |
response = pideCenso('{"query":'+sql+',"vent":null,"r_ini":"'+ str(ini) +'","r_fin":"'+ str(fin) +'"}','BusqCT') | |
if response[0]!='error': | |
cadena_inegi = response[1].split('¬¬') | |
kmls.insert({'estado':estado,'pagina':i,'kml':response[0]}) | |
for escuela in cadena_inegi: | |
if len(escuela.strip())>0: | |
cadena_inegi_datos = escuela.split('*') | |
if len(cadena_inegi_datos)>1: | |
#cadena_inegi_datos[0] -> nombre de la escuela | |
#cadena_inegi_datos[1] -> CCT | |
#cadena_inegi_datos[2], cadena_inegi_datos[3] -> lat,long | |
#cadena_inegi_datos[4] -> Edo | |
#cadena_inegi_datos[5] -> Municipio | |
#cadena_inegi_datos[6] -> Nivel | |
#print cadena_inegi_datos[1] | |
datos_censo = pideCenso('{"cve":"'+cadena_inegi_datos[1]+'"}','InfoWindow') | |
if datos_censo[0]!='error': | |
#datos_censo[0] -> nombre | |
#datos_censo[1] -> tipo cct | |
#datos_censo[2] -> status (censado?) | |
#datos_censo[3] -> #alumnos | |
#datos_censo[4] -> #personal | |
#datos_censo[5] -> calle | |
#datos_censo[6] -> #grupos | |
#datos_censo[7] -> fecha (de?) | |
#datos_censo[8] -> CP | |
#datos_censo[9] -> telefono | |
#datos_censo[10] -> ? | |
#datos_censo[11] -> Edo | |
#datos_censo[12] -> Municipio | |
#datos_censo[13] -> Localidad | |
#datos_censo[14] -> responsable | |
#datos_censo[15] -> turno | |
#datos_censo[16] -> CCT | |
#datos_censo[17] -> numero | |
#datos_censo[18] -> ? | |
#datos_censo[19] -> ? (es un numero) | |
#datos_censo[20] -> ? | |
post = {'cct':cadena_inegi_datos[1], | |
'nombre':cadena_inegi_datos[0], | |
'coord1':cadena_inegi_datos[2], | |
'coord2':cadena_inegi_datos[3], | |
'edo':cadena_inegi_datos[4], | |
'municipio':cadena_inegi_datos[5], | |
'nivel':cadena_inegi_datos[6], | |
'nombre_en_mapa':datos_censo[0], | |
'tipo':datos_censo[1], | |
'status':datos_censo[2], | |
'num_alumnos':datos_censo[3], | |
'num_personal':datos_censo[4], | |
'calle':datos_censo[5], | |
'num_grupos':datos_censo[6], | |
'fecha':datos_censo[7], | |
'cp':datos_censo[8], | |
'telefono':datos_censo[9], | |
'dato1':datos_censo[10], | |
'edo_en_mapa':datos_censo[11], | |
'municipio_en_mapa':datos_censo[12], | |
'localidad_en_mapa':datos_censo[13], | |
'persona_responsable':datos_censo[14], | |
'turno':datos_censo[15], | |
'numero_dir':datos_censo[17], | |
'dato2':datos_censo[18], | |
'dato3':datos_censo[19], | |
'dato4':datos_censo[20], | |
} | |
else: | |
post = {'cct':cadena_inegi_datos[0], | |
'nombre':cadena_inegi_datos[1], | |
'coord1':cadena_inegi_datos[2], | |
'coord2':cadena_inegi_datos[3], | |
'edo':cadena_inegi_datos[4], | |
'municipio':cadena_inegi_datos[5], | |
'nivel':cadena_inegi_datos[6], | |
'error':1 | |
} | |
posts.insert(post) | |
ini = fin + 1 | |
fin = fin + 50 | |
i=i+1 |
a falta de requirements.txt, describo como configuré el setup:
$ virtualenv -p python2.7 venv
Running virtualenv with interpreter /usr/bin/python2.7 ....
$ source venv/bin/activate
(venv)$ export PYCURL_SSL_LIBRARY=openssl
(venv)$ pip install pycurl
(venv) $ mongod &
(venv) $ python censo_2013_inegi.py
2.7 según yo. Igual subo mis archivos de config.
es python 2.7.4 en ubuntu 13.04
suponiendo sudo ...
apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 7F0CEB10
echo 'deb http://downloads-distro.mongodb.org/repo/ubuntu-upstart dist 10gen' | sudo tee /etc/apt/sources.list.d/mongodb.list
apt-get update
apt-get upgrade
apt-get install mongodb-10gen python-pip python2.7-dev
pip install pycurl
pip install pymongo
Después de 54K registros tronó el script:
> db.cemabe_2.count()
54761
>
9351 9400
Traceback (most recent call last):
File "censo_2013_inegi.py", line 70, in <module>
cadena_inegi = response[1].split('¬¬')
IndexError: list index out of range
(venv)Rod@HackBook ~/Desktop/gist8753820-81715af2985a9f886c1747af6a97b78ec08c483a $
@mekler ¿cuántos registros son en total?
Son más de 200k registros. Cuando lo corrí. Se freno en df. Corrí solo df y no hubo error. Seguí todos los demás sin problemas.
@rodowl, modifiqué el código. No validé que el primer response podía no tener datos correctos. mañana corro esto y te comento si todo funciono como debe.
@mekler te importaría pasar el diff del cambio?
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
hey @mekler
es python2?
$ python3 censo_2013_inegi.py
File "censo_2013_inegi.py", line 68
print ini,fin
^
SyntaxError: invalid syntax