Tabla HTML para array PHP

Tengo un calendario escolar en línea, pero quiero tenerlo en mi propia aplicación. Desafortunadamente no puedo hacer que funcione con PHP y expresiones regulares.

El problema es que las celdas de la tabla no están divididas por igual y que cambia por clase. Puedes encontrar el cronogtwig aquí y aquí .

La expresión regular que probé es esta:

(.+?)
(.+?)
(.+?)


¡Pero no funciona correctamente!

La matriz final debe verse más o menos así:

 [0] => Array ( [0] => maandag //the day [1] => 1 //lesson period [2] => MEN, 16, dm //content of the cell ) 

Espero que esta pregunta sea lo suficientemente clara, porque no soy inglés;)

Buena suerte con esto, va a ser complicado … solo ‘usar un analizador de HTML’ en realidad no va a evitar el problema principal, que es la naturaleza de una tabla que utiliza filas de filas. Aunque siempre es un buen consejo utilizar un analizador HTML para analizar grandes cantidades de HTML, si puede dividir ese HTML en fragmentos más pequeños y confiables, entonces el análisis mediante otras técnicas siempre será más óptimo (pero obviamente más propenso a sutiles diferencias inesperadas en el HTML) .

Normaliza la tabla

Si fuera yo, comenzaría con algo que pueda detectar dónde comienza y termina la tabla (ya que no me gustaría analizar toda la página, incluso si utilizo un analizador HTML si no es necesario) :

 $table = $start = $end = false; /// 'Vrijdag' should be unique enough, but will fail if it appears elsewhere $pos = strpos($html, 'Vrijdag'); /// find your start and end based on reliable tags if ( $pos !== false ) { $start = stripos($html, '', $pos); if ( $start !== false ) { $end = stripos($html, '', $start); } } if ( $start !== false && $end !== false ) { /// we can now grab our table $html; $table = substr($html, $start, $end - $start); } 

Luego, debido a la forma casual en que las celdas se extienden verticalmente (pero parecen ser uniformes en sentido horizontal) , elegiría una columna de ‘día’ y trabajaría hacia abajo.

 if ( $table ) { /// break apart based on rows $rows = preg_split('##i', $table); /// foreach ( $rows as $key => $row ) { $rows[$key] = preg_split('##i', $row); } } 

Lo anterior debería darle algo como:

 array ( '0' => array ( '0' => "1", '1' => "" '2' => "3D
009
Hk


" ... ), '0' => array ( '0' => "2", '1' => "" '2' => "Hk
" ... ), )

Ahora que tiene eso, puede escanear en cada fila, y donde preg_match un rowspan, tendría que crear una copia de la información de esa celda en la fila siguiente (en el lugar correcto) para crear una tabla completa estructura (sin filas de filas) .

 /// can't use foreach here because we want to modify the array within the loop $lof = count($rows); for ( $rkey=0; $rkey< $lof; $rkey++ ) { /// pull out the row $row = $rows[$rkey]; foreach ( $row as $ckey => $cell ) { if ( preg_match('/ rowspan=.([0-9]+)./', $cell, $regs) ) { $rowspan = (int) $regs[1]; if ( $rowspan > 1 ) { /// there was a gotcha here, I realised afterwards i was constructing /// a replacement pattern that looked like this '$14$2'. Which meant /// the system tried to find a group at offset 14. To get around this /// problem, PHP allows the group reference numbers to be wraped with {}. /// so we now get the value of '$1' and '$2' inserted around a literal number $newcell = preg_replace('/( rowspan=.)[0-9]+(.)/', '${1}'.($rowspan-1).'${2}', $cell); array_splice( $rows[$rkey+1], $ckey, $newcell ); } } } } 

Lo anterior debe normalizar la tabla para que las filas no sean un problema.

(Tenga en cuenta que lo anterior es un código teórico, lo he escrito manualmente y aún no lo he probado, lo que haré en breve)

Después de la prueba

Hubo algunos pequeños errores con lo anterior que he actualizado, es decir, obtener los argumentos de php para ciertas funciones en el camino equivocado … Después de ordenarlos, parece que funciona:

 /// grab the html $html = file_get_contents('http://www.cibap.nl/beheer/modules/roosters/create_rooster.php?element=CR13A&soort=klas&week=37&jaar=2012'); /// start with nothing $table = $start = $end = false; /// 'Vrijdag' should be unique enough, but will fail if it appears elsewhere $pos = strpos($html, 'Vrijdag'); /// find your start and end based on reliable tags if ( $pos !== false ) { $start = stripos($html, '', $pos); if ( $start !== false ) { $end = stripos($html, '', $start); } } /// make sure we have a start and end if ( $start !== false && $end !== false ) { /// we can now grab our table $html; $table = substr($html, $start, $end - $start); /// convert brs to something that wont be removed by strip_tags $table = preg_replace('#
#i', "\n", $table); } if ( $table ) { /// break apart based on rows (a close tr is quite reliable to find) $rows = preg_split('##i', $table); /// break apart the cells (a close td is quite reliable to find) foreach ( $rows as $key => $row ) { $rows[$key] = preg_split('##i', $row); } } else { /// create so we avoid errors $rows = array(); } /// changed this here from a foreach to a for because it seems /// foreach was working from a copy of $rows and so any modifications /// we made to $rows while the loop was happening were ignored. $lof = count($rows); for ( $rkey=0; $rkey< $lof; $rkey++ ) { /// pull out the row $row = $rows[$rkey]; /// step each cell in the row foreach ( $row as $ckey => $cell ) { /// pull out our rowspan value if ( preg_match('/ rowspan=.([0-9]+)./', $cell, $regs) ) { /// if rowspan is greater than one (ie spread across multirows) $rowspan = (int) $regs[1]; if ( $rowspan > 1 ) { /// then copy this cell into the next row down, but decrease it's rowspan /// so that when we find it in the next row we know how many more times /// it should span down. $newcell = preg_replace('/( rowspan=.)([0-9]+)(.)/', '${1}'.($rowspan-1).'${3}', $cell); array_splice( $rows[$rkey+1], $ckey, 0, $newcell ); } } } } /// now finally step the normalised table and get rid of the unwanted tags /// that remain at the same time split our values in to something more useful foreach ( $rows as $rkey => $row ) { foreach ( $row as $ckey => $cell ) { $rows[$rkey][$ckey] = preg_split('/\n+/',trim(strip_tags( $cell ))); } } echo ''; print_r($rows); echo '';

Utilice un analizador HTML para extraer los valores. Analizador PHP HTML simple vale la pena intentarlo: http://simplehtmldom.sourceforge.net/