2011-06-04 16 views
5

Me gustaría analizar una página HTML con el Nokogiri. Hay una tabla en la parte de la página que no usa ninguna ID específica. Es posible extraer algo como:¿Cómo se analiza una tabla HTML simple con Nokogiri?

Today,3,455,34 
Today,1,1300,3664 
Today,10,100000,3444, 
Yesterday,3454,5656,3 
Yesterday,3545,1000,10 
Yesterday,3411,36223,15 

De este HTML:

<div id="__DailyStat__"> 
    <table> 
    <tr class="blh"><th colspan="3">Today</th><th class="r" colspan="3">Yesterday</th></tr> 
    <tr class="blh"><th>Qnty</th><th>Size</th><th>Length</th><th class="r">Length</th><th class="r">Size</th><th class="r">Qnty</th></tr> 
    <tr class="blr"> 
     <td>3</td> 
     <td>455</td> 
     <td>34</td> 
     <td class="r">3454</td> 
     <td class="r">5656</td> 
     <td class="r">3</td> 
    </tr> 

    <tr class="bla"> 
     <td>1</td> 
     <td>1300</td> 
     <td>3664</td> 
     <td class="r">3545</td> 
     <td class="r">1000</td> 
     <td class="r">10</td> 
    </tr> 

    <tr class="blr"> 
     <td>10</td> 
     <td>100000</td> 
     <td>3444</td> 
     <td class="r">3411</td> 
     <td class="r">36223</td> 
     <td class="r">15</td> 
    </tr> 
    </table> 
</div> 

Respuesta

9

Como rápida y sucia primera pasada que haría:

html = <<EOT 
<div id="__DailyStat__"> 
    <table> 
    <tr class="blh"><th colspan="3">Today</th><th class="r" colspan="3">Yesterday</th></tr> 
    <tr class="blh"><th>Qnty</th><th>Size</th><th>Length</th><th class="r">Length</th><th class="r">Size</th><th class="r">Qnty</th></tr> 
    <tr class="blr"> 
     <td>3</td> 
     <td>455</td> 
     <td>34</td> 
     <td class="r">3454</td> 
     <td class="r">5656</td> 
     <td class="r">3</td> 
    </tr> 

    <tr class="bla"> 
     <td>1</td> 
     <td>1300</td> 
     <td>3664</td> 
     <td class="r">3545</td> 
     <td class="r">1000</td> 
     <td class="r">10</td> 
    </tr> 

    <tr class="blr"> 
     <td>10</td> 
     <td>100000</td> 
     <td>3444</td> 
     <td class="r">3411</td> 
     <td class="r">36223</td> 
     <td class="r">15</td> 
    </tr> 
    </table> 
</div> 
EOT 

# Today    Yesterday 
# Qnty Size Length Length Size Qnty 
# 3 455 34  3454 5656 3 
# 1 1300 3664 3545 1000 10 
# 10 100000 3444 3411 36223 15 


require 'nokogiri' 

doc = Nokogiri::HTML(html) 

Uso de CSS para encontrar el inicio de la tabla, y definir algunos lugares para almacenar los datos que estamos capturando:

table = doc.at('div#__DailyStat__ table') 

today_data  = [] 
yesterday_data = [] 

bucle sobre las filas de la tabla, el rechazo de los encabezados:

table.search('tr').each do |tr| 

    next if (tr['class'] == 'blh') 

arrays Inicializar para capturar los datos pertinentes de cada fila, empujar selectivamente los datos en la matriz apropiada:

today_td_data  = [ 'Today'  ] 
    yesterday_td_data = [ 'Yesterday' ] 

    tr.search('td').each do |td| 
    if (td['class'] == 'r') 
     yesterday_td_data << td.text.to_i 
    else 
     today_td_data << td.text.to_i 
    end 
    end 

    today_data  << today_td_data 
    yesterday_data << yesterday_td_data 

end 

Y salida de los datos:

puts today_data.map{ |a| a.join(',') } 
puts yesterday_data.map{ |a| a.join(',') } 

> Today,3,455,34 
> Today,1,1300,3664 
> Today,10,100000,3444 
> Yesterday,3454,5656,3 
> Yesterday,3545,1000,10 
> Yesterday,3411,36223,15 

sólo para ayudar a visualizar lo que está pasando, a la salida del circuito de "tr", el today_data y yesterday_data matrices son matrices de-matrices buscando como:

[["Today", 3, 455, 34], ["Today", 1, 1300, 3664], ["Today", 10, 100000, 3444]] 

Como alternativa, en lugar de un bucle a través de los tags "TD" y la detección de la clase para la etiqueta, podría haber agarrado el contenido de la "tr" y luego se usa para agarrar scan los números y en rodajas la matriz resultante en "hoy" y "arrays" de ayer:

tr_data = tr.text.scan(/\d+/).map{ |i| i.to_i } 

    today_td_data  = [ 'Today',  *tr_data[0, 3] ] 
    yesterday_td_data = [ 'Yesterday', *tr_data[3, 3] ] 

en el desarrollo del mundo real, como en el trabajo, que haría uso que en lugar de lo que primero escribió porque es sucinto.

Y tenga en cuenta que no utilicé XPath. Es muy factible en Nokogiri usar XPath y lograr esto, pero para simplificar prefiero los accesadores de CSS. XPath habría permitido acceder a contenidos individuales de etiquetas "td", pero también comenzaría a parecerse a ruido de línea, lo cual es algo que queremos evitar al escribir código, ya que afecta el mantenimiento. También podría haber usado CSS para obtener las etiquetas "td" correctas, como 'tr td.r', pero no creo que mejore el código, sino que sería una forma alternativa de hacerlo.

+0

Gracias @ the-tin-man. Funcionó correctamente, solo tengo que cambiar doc.at a doc.css por algún error. Solo tengo un pequeño problema, que intentaré resolver. No tengo suficiente reputación para votar, así que anímate :) – JraNil

+0

'at' funciona tanto con CSS como con XPath, pero solo devuelve la primera aparición del nodo, por lo que puedes tener varias etiquetas' table'. 'css' es un alias de' search' que devuelve un NodeSet, o una matriz de nodos, por lo que debe indexar los resultados o iterar sobre ellos. 'at_css' es el equivalente específico de CSS a' at'. –

+0

@JraNil, También, como un FYI, el código funciona con su HTML de muestra, por lo que debe haber algo que falta en la muestra. Si genera una muestra precisa, podemos proporcionar mejores respuestas. –

Cuestiones relacionadas