Извлечение частей загруженной страницы в PHP (RegEx) - PullRequest
4 голосов
/ 07 февраля 2010

У меня есть система новостной рассылки, которую я пытаюсь внедрить в сайт PHP. Сайт PHP загружает область содержимого, а также загружает скрипты в заголовок страницы. Это прекрасно работает для кода, сгенерированного для сайта, но теперь у меня есть информационный бюллетень, который я пытаюсь включить.

Первоначально я собирался использовать iFrame, но количество вызовов AJAX и jQuery делает это довольно сложным.

Так что я подумал, что мог бы использовать cURL для загрузки страницы новостной рассылки в качестве переменной. Затем я собирался использовать RegEx для захвата контента между тегами тела и размещения его в области контента. Наконец, я собирался снова использовать RegEx для поиска в голове и получения любых скриптов.

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $config_live_site."lib/alerts/user/update.php?email=test@test.com.au"); # URL to post to
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1 ); # return into a variable
curl_setopt($ch, CURLOPT_HEADER, 0);
$loaded_result = curl_exec( $ch ); # run!
curl_close($ch);

// Capture the body content and place in $_content
if (preg_match('%<body>([\s\S]*)</body>%', $loaded_result, $regs)) {
 $_content .= $regs[1];
} else {
 $_content .= "<p>No content to display.</p>";
}

// Capture the scripts and place in the head
if (preg_match('%(<script type="text/javascript">[\s\S]*</script>)%', $loaded_result, $regs)) {
 $headDetails .= $regs[0];
}

Это работает большую часть времени, но если в теле документа есть скрипт, он записывает его до последнего /script'.

Мне кажется, мой вопрос двоякий ...

A. Есть ли лучший общий подход (мой крайний срок очень короткий, поэтому это должно быть быстрое решение без слишком большого редактирования кода бюллетеня)?

B. Какой RegEx мне нужно использовать, чтобы просто захватить первый скрипт?

Ответы [ 4 ]

2 голосов
/ 07 февраля 2010

Я думаю, вам нужно добавить ? к регулярному выражению скрипта после *, чтобы он не был жадным. Жадное совпадение с регулярным выражением в максимально возможной степени (все, что находится между первым открывающим тегом и последним закрытием), нежадное совпадение как можно меньше (только то, что находится между открывающим тегом и первым закрывающим тегом). Попробуйте:

%(<script type="text/javascript">[\s\S]*?</script>)%

Как уже упоминалось, измените его на preg_match_all, и вы должны просто сопоставить отдельные разделы сценария, а не все между первым и последним тегами сценария.

1 голос
/ 07 февраля 2010

A: Я не вижу проблем с использованием регулярных выражений для извлечения необходимых фрагментов из HTML-страниц, которые не обязательно являются действительными. Фактически, некоторые из паучьих решений, с которыми я работал, сделали именно это.

B: используйте preg_match_all () вместо preg_match (). preg_match () захватывает только первое совпадение, тогда как preg_match_all () будет продолжаться до конца строки и будет возвращать все совпадения.

0 голосов
/ 07 февраля 2010

Быстрый и грязный ответ может быть следующим: удалить содержимое тела сразу после его захвата. Затем продолжите

if (preg_match('%<head>([\s\S]*)</head>%', $loaded_result, $regs)) {
   $_header .= $regs[1];
} else {
   $_header .= "<p>No content to display.</p>";
}

затем примените регулярное выражение только к заголовку

if (preg_match('%(<script type="text/javascript">[\s\S]*</script>)%', $_header, $regs)) {
   $headDetails .= $regs[0];
}

Если HTML, который вы получаете от curl, правильно сформирован, вы должны использовать simplexml для выполнения извлечения. Как следует из названия, он очень прост в использовании.

$xml = simplexml_load_string($loaded_content);

$body = $xml->body->asXML();

$scripts = $xml->xpath('//head/script');
foreach ($scripts as $script) {
  $_scripts .= $script->asXML();
}

Если ваш html не правильно сформирован, то вы должны прибегнуть к аккуратности, чтобы его нормализовать (или, лучше, исправьте сценарии, которые выводят недопустимый html-контент)

0 голосов
/ 07 февраля 2010
$doc = new DOMDocument();
$doc->loadHTML($loaded_result);
$xpath = new DOMXpath($doc);

$kod = $xpath->query("//head/script");
$i = 0;
foreach($kod as $node){
    echo 'im the script nº'.(++$i).' in the head and this is my content: ';
    echo $doc->saveXML($node)."\n";
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...