У меня есть школьный календарь онлайн, но я хочу иметь его в своем приложении. К сожалению, я не могу заставить его работать с PHP и регулярным выражением.
Проблема в том, что ячейки таблицы не разделены поровну и что они изменяются для каждого класса. Вы можете найти расписание здесь и здесь .
Регулярное выражение, которое я пробовал, следующее:
<td rowspan='(?:[0-9]{1,3})' class='value'>(.+?)<br/>(.+?)<br/>(.+?)<br/><br/><br/></td>
Но это работает неправильно!
Конечный массив должен выглядеть примерно так:
[0] => Array ( [0] => maandag //the day [1] => 1 //lesson period [2] => MEN, 16, dm //content of the cell )
Я надеюсь, что этот вопрос достаточно ясен, потому что я не английский;)
Удачи вам в этом, это будет сложно … просто «использование парсера HTML» на самом деле не позволит избежать основной проблемы, которая является характером таблицы, в которой используются ряды строк. Несмотря на то, что всегда полезно использовать HTML-парсер для синтаксического анализа больших объемов HTML, если вы можете разбить этот HTML на более мелкие надежные куски, тогда анализ с использованием других методов всегда будет более оптимальным (но, очевидно, более подверженным тонкие неожиданные различия в HTML) .
Если бы это был я, я бы начал с чего-то, что может обнаружить, где начинается и заканчивается ваша таблица (поскольку я бы не хотел анализировать всю страницу даже при использовании HTML Parser, если мне это не нужно) :
$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, '<tr>', $pos); if ( $start !== false ) { $end = stripos($html, '</table>', $start); } } if ( $start !== false && $end !== false ) { /// we can now grab our table $html; $table = substr($html, $start, $end - $start); }
Затем из-за случайного пути ячейки натянуты вертикально (но кажутся однородными по горизонтали), я бы выбрал колонку «день» и работал вниз.
if ( $table ) { /// break apart based on rows $rows = preg_split('#</tr>#i', $table); /// foreach ( $rows as $key => $row ) { $rows[$key] = preg_split('#</td>#i', $row); } }
Вышеупомянутое должно дать вам что-то вроде:
array ( '0' => array ( '0' => "<td class='heading'>1", '1' => "<td rowspan='1' class='empty'>" '2' => "<td rowspan='5' class='value'>3D<br/>009<br/>Hk<br/><br/><br/>" ... ), '0' => array ( '0' => "<td class='heading'>2", '1' => "<td rowspan='2' class='empty'>" '2' => "<td rowspan='3' class='value'>Hk<br/>" ... ), )
Теперь, когда у вас есть это, вы можете сканировать по каждой строке и где preg_match rowspan, вам нужно будет создать копию информации этой ячейки в строке ниже (в нужном месте), чтобы фактически создать полную таблицу Структура (без строк) .
/// 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 ); } } } }
Вышеизложенное должно нормализовать таблицу, так что ряды столбцов больше не являются проблемой.
(Обратите внимание, что приведенный выше теоретический код, я набрал его вручную и еще не проверил его – что я буду делать в ближайшее время)
Было несколько небольших ошибок с вышеизложенным, что я обновил, а именно, чтобы получить аргументы php для определенных функций вокруг неправильного пути … После сортировки они работают:
/// 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, '<tr>', $pos); if ( $start !== false ) { $end = stripos($html, '</table>', $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('#<br ?/>#i', "\n", $table); } if ( $table ) { /// break apart based on rows (a close tr is quite reliable to find) $rows = preg_split('#</tr>#i', $table); /// break apart the cells (a close td is quite reliable to find) foreach ( $rows as $key => $row ) { $rows[$key] = preg_split('#</td>#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 '<xmp>'; print_r($rows); echo '</xmp>';
Для извлечения значений используйте анализатор HTML. PHP Простой HTML-парсер стоит того: http://simplehtmldom.sourceforge.net/