| You are here: Inicio > Inmersión en Python > Procesamiento de HTML > Extracción de datos de documentos HTML | << >> | ||||
Inmersión en PythonPython de novato a experto |
|||||
Para extraer datos de documentos HTML derivaremos la clase SGMLParser y definiremos métodos para cada etiqueta o entidad que queramos capturar.
El primer paso para extrar datos de un documento HTML es obtener un HTML. Si tiene algún documento en su disco duro, use las funciones de ficheros para leerlo, pero lo divertido empezará cuando lo usemos sobre HTML sacado directamente de páginas web.
>>> import urllib>>> sock = urllib.urlopen("http://diveintopython.org/")
>>> htmlSource = sock.read()
>>> sock.close()
>>> print htmlSource
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head> <meta http-equiv='Content-Type' content='text/html; charset=ISO-8859-1'> <title>Dive Into Python</title> <link rel='stylesheet' href='diveintopython.css' type='text/css'> <link rev='made' href='mailto:mark@diveintopython.org'> <meta name='keywords' content='Python, Dive Into Python, tutorial, object-oriented, programming, documentation, book, free'> <meta name='description' content='a free Python tutorial for experienced programmers'> </head> <body bgcolor='white' text='black' link='#0000FF' vlink='#840084' alink='#0000FF'> <table cellpadding='0' cellspacing='0' border='0' width='100%'> <tr><td class='header' width='1%' valign='top'>diveintopython.org</td> <td width='99%' align='right'><hr size='1' noshade></td></tr> <tr><td class='tagline' colspan='2'>Python for experienced programmers</td></tr> [...cortamos...]
| El módulo urllib es parte de la biblioteca estándar de Python. Contiene funciones para obtener información sobre URLs (páginas web, principalmente) y para descargar datos desde ellas. | |
| El uso más simple de urllib es la descarga del texto completo de una página web usando la función urlopen. Abrir una URL es similar a abrir un fichero. El valor de retorno de urlopen es un objeto parecido al de un fichero, y tiene algunos de sus mismos métodos. | |
| La operación más sencilla que puede realizar con el objeto devuelto por urlopen es read, que lee el HTML completo de la página web y lo almacena en una cadena de texto. El objeto también admite readlines, que devuelve el texto línea por línea en una lista. | |
| Cuando haya terminado con el objeto, asegúrese de cerrarlo (close), igual que con un objeto de fichero normal. | |
| Ahora tenemos el HTML completo de la página principal de http://diveintopython.org/ en una cadena, preparado para su análisis. |
Si aún no lo ha hecho, puede descargar éste ejemplo y otros usados en este libro.
from sgmllib import SGMLParser class URLLister(SGMLParser): def reset(self):SGMLParser.reset(self) self.urls = [] def start_a(self, attrs):
href = [v for k, v in attrs if k=='href']
![]()
if href: self.urls.extend(href)
| reset lo invoca el método __init__ de SGMLParser y también se le puede llamar de forma manual una vez se ha creado la instancia del analizador. Si necesita hacer cualquier tipo de inicialización póngalo en reset, no en __init__, de manera que se reinicialice adecuadamente cuando alguien reutilice una instancia del analizador. | |
| start_a lo invoca SGMLParser cada vez que encuentra una etiqueta <a>. La etiqueta puede contener un atributo href y otros, como name o title. El parámetro attrs es una lista de tuplas [(atributo, valor), (atributo, valor), ...]. O puede que sea sólo una <a>, que es una etiqueta HTML válida (aunque inútil), en cuyo caso attrs será una lista vacía. | |
| Puede averiguar si esta etiqueta <a> tiene un atributo href con una simple lista por comprensión multivariable. | |
| Las comparaciones de cadenas como k=='href' siempre distiguen las mayúsculas, pero en este caso no hay peligro porque SGMLParser convierte los nombres de los atributos a minúsculas cuando construye attrs. |
>>> import urllib, urllister >>> usock = urllib.urlopen("http://diveintopython.org/") >>> parser = urllister.URLLister() >>> parser.feed(usock.read())>>> usock.close()
>>> parser.close()
>>> for url in parser.urls: print url
toc/index.html #download #languages toc/index.html appendix/history.html download/diveintopython-html-5.0.zip download/diveintopython-pdf-5.0.zip download/diveintopython-word-5.0.zip download/diveintopython-text-5.0.zip download/diveintopython-html-flat-5.0.zip download/diveintopython-xml-5.0.zip download/diveintopython-common-5.0.zip ... se omite el resto de la salida para abreviar ...
| Invoque el método feed, definido en SGMLParser, para alimentar el HTML al analizador.[5] Acepta una cadena, que es lo que devuelve usock.read(). | |
| Igual que con los objetos, debería cerrar (close) sus objetos URL tan pronto como acabe de usarlos. | |
| Debería cerrar (close) también el objeto analizador, pero por una razón diferente. Ha leído todos los datos y se los ha dado al analizador, pero el método feed no garantiza que se haya procesado todo el HTML que le pasó; puede haberlo almacenado en un búfer, y estar esperando por más. Asegúrese de invocar close para forzar el vaciado del búfer y que se analice todo por completo. | |
| Una vez cerrado el analizado queda completo el análisis, y parser.urls contiene una lista de todas las URLs con las que enlaza el documento HTML. (Su salida puede ser diferente, si se han actualizado los enlaces de descarga para cuando usted lea esto). |
[5] El término técnico para un analizador como SGMLParser es consumidor: consume HTML y lo separa en partes. Es presumible que el nombre feed se escogiera para ajustarse a la idea de “consumidor”. Personalmente, me hace pensar en una atracción en el zoológico donde sólo hay una jaula oscura sin árboles ni plantas ni evidencia de vida de ninguna clase, pero si uno se queda perfectamente quieto y observa desde muy cerca, puede llegar a ver dos ojos ovalados que le devuelven la mirada desde la esquina más alejada, aunque uno se convence de que sólo es su imaginación que le está gastando una broma, y lo única manera de que uno pueda decir que eso no es sólo una jaula vacía es una pequeña e inocua señal en las rejas que reza, “No dé de comer al analizador”. Pero quizá es sólo cosa mía. De cualquier manera, es una imagen mental interesante.
<< Presentación de sgmllib.py |
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | |
Presentación de BaseHTMLProcessor.py >> |