PHP html scraping - PullRequest
       40

PHP html scraping

0 голосов
/ 04 ноября 2011

Это мой первый пост на сайте, так что терпите меня

Хорошо, я новичок в PHP, и у меня есть особая потребность в этом для моего проекта. Я надеюсь, что некоторые из вас, ребята, могли бы помочь!

По сути, я хочу почистить веб-страницу и получить доступ к определенной HTML-таблице и ее информации. Мне нужно разобрать эту информацию и просто отформатировать ее в желаемом результате.

Итак, с чего начать ..... вот мой php я уже написал

<?php

$url = "http://www.goldenplec.com/festivals/oxegen-2/oxegen-2011";
$raw = file_get_contents($url);

$newlines = array("\t","\n","\r","\x20\x20","\0","\x0B");
$content = str_replace($newlines, "", html_entity_decode($raw));

$start = strpos($content,'<table style="background: #FFF; font-size: 13px;"');
$end = strpos($content,'</table>',$start) + 8;

$table = substr($content,$start,$end-$start);

echo $table;


/* Regex here to echo the desired result */


?>

Этот URL содержит нужную мне таблицу. Мой код просто отобразит эту точную таблицу.

Однако, и вот в чем заключается моя проблема, я ни в коем случае не являюсь опытным экспертом, и мне нужно отображать данные из таблицы в определенном формате. Я хочу отобразить XML-файл, содержащий несколько операторов вставки SQL следующим образом:

$xml_output .= "<statement>INSERT INTO timetable VALUES(1,'Black Eyed Peas','Main Stage','Friday', '23:15')</statement>";
$xml_output .= "<statement>INSERT INTO timetable VALUES(2,'Swedish House Mafia','Vodafone Stage','Friday', '23:30')</statement>";
$xml_output .= "<statement>INSERT INTO timetable VALUES(3,'Foo Fighters','Main Stage','Saturday', '23:25')</statement>";
$xml_output .= "<statement>INSERT INTO timetable VALUES(4,'Deadmau5','Vodafone Stage','Saturday', '23:05')</statement>";
$xml_output .= "<statement>INSERT INTO timetable VALUES(5,'Coldplay','Main Stage','Sunday', '22:25')</statement>";
$xml_output .= "<statement>INSERT INTO timetable VALUES(6,'Pendalum','Vodafone Stage','Sunday', '22:15')</statement>";

Я надеюсь, что предоставил достаточно информации, и я был бы очень признателен за любую помощь от вас, добрый народ.

Заранее спасибо.

1 Ответ

2 голосов
/ 04 ноября 2011

Вам гораздо лучше использовать что-то вроде XPATH, когда будете делать очистку. Я получаю все элементы <TD>, определяю, что место проведения всегда UPPERCASE, поэтому мы можем использовать это в своих интересах. У нас также есть список дней и пробелы, поэтому я пропускаю их. Я определяю начало раздела актов посредством проверки на ":", который обозначает время. Учитывая, что событие длится 3 дня, а расположение данных чередуется для каждого дня, я просто увеличиваю день, а затем сбрасываю его, когда оно достигает последнего дня события.

Возможно, здесь возникают некоторые проблемы с кодировкой символов, но не хотелось слишком много вмешиваться в это. Возможно, есть более элегантные решения.

Редактировать: только что заметил, что не все действия чередуются точно на 3 дня, поэтому будет сложнее получить день события. Код ниже не даст точных дней для каждого действия. В основном "Little Green Cars" и "Touchwood"

Edit2: код теперь обновлен и должен разобрать все действия правильно с правильной датой. Даты нарушения, у которых ничего не запланировано, представлены двумя пустыми строками (""). Мы можем обнаружить это и увеличить наш счетчик $day.

<?php

libxml_use_internal_errors(true);

$url = "lineup2011.html";
$rawHTML = file_get_contents($url);

$dom = new DOMDocument();
$dom->loadHTML($rawHTML);


$xpath = new DOMXPath($dom);

$nodeList = $xpath->query("//table//td");

$nodeCount = 0;
$venue = "";
$day = 0;
$acts = array();

while ($nodeCount < $nodeList->length) {
    $value = $nodeList->item($nodeCount)->nodeValue;

    if (isUpper($value) && strpos($value, ":") === false && $value != "") {
        $venue = $value;
        $nodeCount += 7;
        $day = 0;
        continue;
    }

    if ($value == "" && $nodeList->item($nodeCount + 1)->nodeValue == "") {
        $day++;
        $nodeCount += 2;
        continue;
    }

    $act = array();
    $act['time'] = $value;
    $act['name'] = $nodeList->item($nodeCount + 1)->nodeValue;
    $act['venue'] = $venue;

    $act['day'] = $day % 3;


    $day++;

    $acts[] = $act;
    $nodeCount += 2;
}

print_r($acts);


function isUpper($str) {
    return (strtoupper($str) == $str);
}
...