Skip to content

Instantly share code, notes, and snippets.

@jdelacueva
Created August 31, 2011 11:09
Show Gist options
  • Save jdelacueva/1183312 to your computer and use it in GitHub Desktop.
Save jdelacueva/1183312 to your computer and use it in GitHub Desktop.
Extracción de datos de los senadores de la novena legislatura
#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
Copyright: Javier de la Cueva
Licencia: Affero GPL V3
Script para generar un archivo csv con datos de los senadores de la
novena legislatura.
Uso:
----
Ejecute en una línea de comandos:
$ python senadores_novena.py
Encontrará el archivo generado mediante dicha orden en el mismo
directorio que el script.
"""
import os
import csv
import re
import urllib2
from datetime import date
from lxml.html import parse
cwd = os.getcwd()
join = os.path.join
root_path = os.path.dirname(cwd)
fecha_hoy = date.today().strftime('%Y-%m-%d')
# Constantes
# ----------
# Si se desea, cambiar acorde con los directorios donde se almacenen los datos
outfile = join(root_path, '%s_senadores_novena_legislatura.csv' % fecha_hoy)
# Si se desea, cambiar según la legislatura cuyos datos se desean extraer
url = 'http://www.senado.es/solotexto/legis9/senadores/alfabet.html'
# Constantes correspondientes a la información a generar
nombre_parlamento = 'Senado'
jurisdiccion = 'Estado'
legislatura = 'Legislatura IX'
# Funciones
# ---------
#
# Hay 4 funciones:
#
# 1. def get_tree(url):
#
# Descarga una página web y genera su árbol.
#
# 2. get_urls_senadores(url):
#
# Construye una lista con todas las páginas públicas de los
# senadores.
#
# 3. extraer_datos(url):
#
# Extrae los datos relevantes de la página pública de un senador y
# construye un diccionario con ellos.
#
# 4 crear_csv(urls, outfile):
#
# Crea un archivo de valores separados por comas con el diccionario
# obtenido mediante la función `extraer_datos(url)`. Toma como
# parámetros la lista de urls públicas de los senadores y el nombre
# del archivo que se genera.
#
def get_tree(url):
"""
Descarga y genera el árbol de una página web. La conexión mostrará
cabeceras User-agent Mozilla/5.0 por ser necesarias para ser aceptada
por determinados servidores web.
Uso::
>>> homepage = get_tree('http://www.senado.es')
"""
# TODO: Crear excepción si no hay conexión.
opener = urllib2.build_opener()
opener.addheaders = [('User-agent', 'Mozilla/5.0')]
sock = opener.open(url)
tree = parse(sock).getroot()
sock.close()
return tree
def get_urls_senadores(url):
"""
Crea una lista de urls de los senadores de la novena legislatura.
Toma como parámetro la url base donde se halla la lista de todos
los senadores de dicha legislatura, extrae las urls
correspondientes a la página pública de cada senador y crea una
lista con las urls extraídas.
"""
lista_urls = list()
tree = get_tree(url)
seleccion = tree.xpath('//li')
prefijo = 'http://www.senado.es/solotexto/legis9/senadores/'
for item in seleccion:
url = prefijo + item.getchildren()[0].attrib['href']
lista_urls.append(url)
return lista_urls
def extraer_datos(url):
"""
Extrae los datos relevantes de la página pública de un senador.
Toma como parámetro la url de la página pública.
"""
tree = get_tree(url)
# Nombre y apellidos
nombre_apellidos = tree.xpath('//b')[0].text.encode('utf-8')
nombre = nombre_apellidos.split(',')[1].strip()
apellido_1 = nombre_apellidos.split(',')[0].strip()
apellido_2 = ""
# Fecha inicio y fin
fecha_inicio = tree.xpath('//li')[0].text_content().split(u' desde el día ')[1].strip('.')
fecha_fin = ""
# Legislatura, nombre parlamento, jurisdiccion: son constantes
# definidas más arriba.
# Nombre y tipo de circunscripción
nombre_circunscripcion = tree.xpath('//li')[0].text_content().split(u' desde el día ')[0].split(' por ')[1].encode('utf-8')
tipo_circunscripcion = "" # TODO: provincia, comunidad autónoma, isla.
# Partido político y grupo parlamentario
seleccion = tree.xpath('/html/body/blockquote/ul/li')
for item in seleccion:
if item.text == u'Partido Político: ':
partido_politico = item.text_content().split(':')[1].strip().title().encode('utf-8')
break
else:
partido_politico = "Desconocido"
try:
grupo_parlamentario = tree.xpath('//li//a')[1].text.strip().encode('utf-8')
except AttributeError:
grupo_parlamentario = tree.xpath('//li//a')[2].text.strip().encode('utf-8')
# Email
if tree.xpath('//a')[0].text_content() == '[correo]':
email = tree.xpath('//a')[0].attrib['href'].split(':')[1]
else:
email = "Sin datos"
return {'id_parlamentario': "",
'nombre_apellidos': nombre_apellidos,
'nombre': nombre,
'apellido_1': apellido_1,
'apellido_2': apellido_2,
'fecha_inicio': fecha_inicio,
'fecha_fin': fecha_fin,
'legislatura': legislatura,
'nombre_parlamento': nombre_parlamento,
'jurisdiccion': jurisdiccion,
'nombre_circunscripcion': nombre_circunscripcion,
'tipo_circunscripcion': tipo_circunscripcion,
'partido_politico': partido_politico,
'grupo_parlamentario': grupo_parlamentario,
'url': url,
'email': email
}
def crear_csv(urls, outfile):
"""
Crea un archivo de valores separados por comas con las cabeceras y
los datos por diputado.
Toma como parámetros la lista de urls de las páginas públicas de
los senadores y el nombre del archivo que se desea generar.
"""
out = csv.writer(open(outfile,"w"), delimiter=',', quoting=csv.QUOTE_ALL)
cabeceras = ['id_parlamentario', 'nombre_apellidos', 'nombre', 'apellido_1',
'apellido_2', 'fecha_inicio', 'fecha_fin', 'legislatura',
'nombre_parlamento', 'jurisdiccion', 'nombre_circunscripcion',
'tipo_circunscripcion', 'partido_politico',
'grupo_parlamentario', 'url', 'email']
out.writerow(cabeceras)
for item in urls:
data = extraer_datos(item)
row = [data['id_parlamentario'], data['nombre_apellidos'],
data['nombre'], data['apellido_1'], data['apellido_2'],
data['fecha_inicio'], data['fecha_fin'], data['legislatura'],
data['nombre_parlamento'], data['jurisdiccion'],
data['nombre_circunscripcion'], data['tipo_circunscripcion'],
data['partido_politico'], data['grupo_parlamentario'],
data['url'], data['email']]
print row # Para debug, también útil para ver la marcha del script
out.writerow(row)
if __name__ == '__main__':
urls = get_urls_senadores(url)
crear_csv(urls, outfile)
@mpmetal
Copy link

mpmetal commented Jan 19, 2015

Hey... lo estoy corriendo pero me da un error,.
You have new mail.
You have new mail.
cd '/Users/mpmetal/Downloads/sacardatos/' && '/usr/bin/pythonw' '/Users/mpmetal/Downloads/sacardatos/senado_novena.py' && echo Exit status: $? && exit 1
Imac-Mp:~ mpmetal$ cd '/Users/mpmetal/Downloads/sacardatos/' && '/usr/bin/pythonw' '/Users/mpmetal/Downloads/sacardatos/senado_novena.py' && echo Exit status: $? && exit 1
Traceback (most recent call last):
File "/Users/mpmetal/Downloads/sacardatos/senado_novena.py", line 27, in
from lxml.html import parse
ImportError: No module named lxml.html
Imac-Mp:sacardatos mpmetal$

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment