2010-05-20 35 views
11

Tengo un documento html y quiero extraer las tablas de este documento y devolverlas como matrices. Me estoy imaginando 2 funciones, una que encuentra todas las tablas html en un documento, y una segunda que convierte las tablas html en matrices bidimensionales.Cómo convertir una tabla HTML en una matriz en python

Algo como esto:

htmltables = get_tables(htmldocument) 
for table in htmltables: 
    array=make_array(table) 

Hay 2 capturas: 1. Las tablas de números varía día a día 2. Las mesas de todo tipo de formato extra raro, como etiquetas de negrita y de parpadeo, arrojado al azar en.

Gracias!

Respuesta

1

Pandas puede extraer todas las tablas en tu html para una lista de tramas de datos nada más sacarlo de la caja, lo que evita tener que analizar manualmente la página (reinventando la rueda). Un DataFrame es un poderoso tipo de matriz bidimensional.

Recomiendo seguir trabajando con los datos a través de Pandas ya que es una gran herramienta, pero también puede convertir a otros formatos si lo prefiere (lista, diccionario, archivo csv, etc.).

Ejemplo

"""Extract all tables from an html file, printing and saving each to csv file.""" 

import pandas as pd 

df_list = pd.read_html('my_file.html') 

for i, df in enumerate(df_list): 
    print df 
    df.to_csv('table {}.csv'.format(i)) 

Conseguir el contenido HTML directamente desde la web en lugar de partir de un archivo requieren sólo una ligera modificación:

import requests 

html = requests.get('my_url').content 
df_list = pd.read_html(html) 
18

Use BeautifulSoup (recomiendo 3.0.8). Encontrar todas las tablas es trivial:

import BeautifulSoup 

def get_tables(htmldoc): 
    soup = BeautifulSoup.BeautifulSoup(htmldoc) 
    return soup.findAll('table') 

Sin embargo, en Python, un array es de 1 dimensión y limitado a unos bonitos tipos elementales como elementos (números enteros, flotadores, que primaria). Así que no hay forma de exprimir una tabla HTML en Python array.

¿Quizás te refieres a Python list? Eso también es unidimensional, pero cualquier elemento puede ser un artículo, por lo que podría tener una lista de listas (una sublista por etiqueta tr, imagino, que contiene un elemento por etiqueta td).

que daría a:

def makelist(table): 
    result = [] 
    allrows = table.findAll('tr') 
    for row in allrows: 
    result.append([]) 
    allcols = row.findAll('td') 
    for col in allcols: 
     thestrings = [unicode(s) for s in col.findAll(text=True)] 
     thetext = ''.join(thestrings) 
     result[-1].append(thetext) 
    return result 

Esto no puede sin embargo ser bastante lo que quiere (no omitir comentarios HTML, los elementos de las listas secundarias son cadenas Unicode y no cadenas de bytes, etc.), pero debe ser fácil de ajustar

+1

Hermosa sopa es grande y fácil! También intente usar lxml + xpath si busca más velocidad. –

+0

wow, que funcionó a la perfección. ¡Gracias! – Zach

+0

@user, siempre contento de ayudar.Si es una respuesta tan buena a su pregunta, debe "aceptarla" (haciendo clic en el icono con forma de marca de verificación debajo del número de votos en la parte superior izquierda de la respuesta) - ¡esa es una parte clave de la etiqueta de SO! -) –

1

A +1 al que pregunta y otro al dios de Python.
Quería probar este ejemplo usando los selectores de lxml y CSS.
Sí, esto es en su mayoría los mismos que el ejemplo de Alex:

import lxml.html 
markup = lxml.html.fromstring('''<html><body>\ 
<table width="600"> 
    <tr> 
     <td width="50%">0,0,0</td> 
     <td width="50%">0,0,1</td> 
    </tr> 
    <tr> 
     <td>0,1,0</td> 
     <td>0,1,1</td> 
    </tr> 
</table> 
<table> 
    <tr> 
     <td>1,0,0</td> 
     <td>1,<blink>0,</blink>1</td> 
     <td>1,0,2</td> 
     <td><bold>1</bold>,0,3</td> 
    </tr> 
</table> 
</body></html>''') 

tbl = [] 
rows = markup.cssselect("tr") 
for row in rows: 
    tbl.append(list()) 
    for td in row.cssselect("td"): 
    tbl[-1].append(unicode(td.text_content())) 

pprint(tbl) 
#[[u'0,0,0', u'0,0,1'], 
# [u'0,1,0', u'0,1,1'], 
# [u'1,0,0', u'1,0,1', u'1,0,2', u'1,0,3']] 
+0

Es extraño usar 'list()' en lugar de plain '[]'. – jfs

+0

@ J.F. Sí, supongo que sí. Gracias por los comentarios y por todas sus excelentes respuestas :-) Continúen con el buen trabajo. – bernie

+0

@ccpizza: excelente punto, gracias. He actualizado el código. – bernie

Cuestiones relacionadas