|
|
|
| В продолжение темы http://softtime.ru/forum/read.php?id_forum=1&id_theme=32573&page=1
Хотел сделать ф-цию, которая разбирает все спортивные RSS-потоки (например адрес RSS передается в параметре ф-ции), но вот обе ф-ции, представленные в той теме, например
<?php
$content = file_get_contents("http://news.yandex.ru/Russia/computers.rss");
preg_match_all("!<item>\s*<title>(.+)</title>\s*".
"<link>(.+)</link>\s*".
"<description>(.+)</description>\s*".
"<pubDate>(.+)</pubDate>.+</item>!isU", $content, $m);
for ( $i = 0; $i < count($m[0]); $i++ ) {
print '<h3><a href="'.$m[2][$i].'">'.$m[1][$i]."</a></h3>\n".
"<p>".htmlspecialchars_decode($m[3][$i]).
"</br>\n".$m[4][$i]."</p></br>\n\n";
}
?>
|
не работают если дата и описание новости меняются местами итд. А именно:
1) поток яндекса
<item>
<title>Сборная России по футболу оказалась под арестом</title>
<link>http://news.yandex.ru/yandsearch?cl4url=www.utro.ru/news/2007/03/23/635194.shtml&country=Russia</link>
<description>Сборная России в преддверие матча против команды Эстонии оказалась под арестом.<br>Однако, несмотря на это, Кержаков, Сычев, Малафеев и молодой Савин все равно ушли на прогулку по городу.<br></description>
<pubDate>Fri, 23 Mar 2007 09:47:58 +0300</pubDate>
<guid>http://news.yandex.ru/yandsearch?cl4url=www.utro.ru/news/2007/03/23/635194.shtml&country=Russia</guid>
</item>
2) поток sportsdaily
<item>
<title>Оба Гуса решают кадровые проблемы</title>
<pubDate>Fri, 23 Mar 2007 17:58:55 GMT</pubDate>
<description>Сборная Эстонии ни разу не пробивалась на крупные международные турниры. В рамках же отборочных турниров к чемпионату Европы она одержала лишь четыре победы в 21 матче. Но даже на этом безрадостном фоне очередная отборочная кампания выглядит удручающе: эстонская сборная под руководством голландского наставника Йелле Гуса в трех матчах не набрала ни одного очка, уступив Македонии, Израилю и России. При этом эстонцы не сумели забить ни одного мяча. После серии неудач пошли оживленные разговоры о том, что Гус может потерять свой пост. Тем не менее голландцу был дан еще один шанс выстроить новую команду с прицелом на будущее.</description>
<link>http://www.sportsdaily.ru/issue.aspx/390/9006</link>
<guid>http://www.sportsdaily.ru/issue.aspx/390/9006</guid>
<category>Статьи</category>
<author> Дмитрий Нечипоренко</author>
</item>
можно ли как-то сделать, чтоб разбор этих лент шел одинаково вне зависимости от того, в каком порядке следуют элементы? | |
|
|
|
|
|
|
|
для: 1999
(23.03.2007 в 10:21)
| | вырезать текст и дату регулярными выражениями и все...
набор регулярных выражений (а не одно) для разный сайтов-источников для вырезки того или иного блока и потом вывод в своем формате. | |
|
|
|
|
|
|
|
для: ZuArt
(23.03.2007 в 10:44)
| | ну к слову в первом посте разбор и идет регулярными...
не писать же к каждому сайту свое регулярное выражение... или все же придется? | |
|
|
|
|
|
|
|
для: 1999
(23.03.2007 в 10:50)
| | на самом деле ничего нету проще...
даж простой пример (катаю навскидку - требуется правка)
$item = " Считанный блок всей новости";
$reg = array();
$reg[сайт 1] = array("ttl"=>"<title>...</title>", "desc"=>".....");
$reg[сайт 2] = array("ttl"=>"<title>...</title>", "desc"=>".....");
$reg[сайт 3] = array("ttl"=>"<title>...</title>", "desc"=>".....");
$itm = array();
foreach($reg[нужный сайт] as $key => $val)
{
if(preg_match($val, $item, $tmp));
$itm[$key] = $tmp[...];
};
|
И независимо от сайта и способа его публикации в массиве $itm будет ЧЕТКО структурированный набор его элементов. | |
|
|
|
|
|
|
|
для: ZuArt
(23.03.2007 в 10:59)
| | ЗЫ. Набор регулярных выражений можно вообще вынести в отдельный файл - тогда править их, если что, будет совсем просто - не придется трогать основной код воообще... поправил нужные строчки для нужного сайта и не морочишься =)
а индексами такого массива могут просто быть адреса или url-ы =))) типа
$arr["sport.yandex.ru"] = array(...)
$arr["sport.ru"] = array(...)
и т.д. | |
|
|
|
|
|
|
|
для: 1999
(23.03.2007 в 10:21)
| | т.е. в любом случае адреса сайтов указываются изначально и для каждого надо писать свое регулярное выражение. так? | |
|
|
|
|
|
|
|
для: 1999
(23.03.2007 в 11:33)
| | не обязательно =)
можно указать один из наборов как общий... и просто проверять типа
$tpls = $arr["общий набор шаблонов"];
if(isset($arr["сайт"]))
$tpls = $arr["сайт"];
|
и делее в цикле работать не с $arr[сайт] а с $tpls =)
А описывать доп шаблоны тока в случае расхождения с общим...
а в плане разделения регилярного выражения на неск блоков - оно того стоит - просто логику просще отлавливать и праить... Но в принципе можно создавать и целостное рег. выражения для сайта - типа как изначально в теме... просто для каждого сайта свое большое выражение + одно общее для всех остальных =) но я бы так делать не стал, т.к. более трудоемкая операция отладки при изменениях =) | |
|
|
|
|
|
|
|
для: 1999
(23.03.2007 в 11:33)
| | не блин... в FireFox все RSS разбираются вне зависимости от того, в каком порядке следуют элементы...
как же это реализовано там? | |
|
|
|
|
|
|
|
для: 1999
(23.03.2007 в 11:50)
| | не путай FF - браузер клиент (встроенный механизм разбора ЕСТЬ и как там реализовано - знают ток разработчики FF)... и СКРИПТ, который получает данные в том виде, котором есть и в котором нужно механим разбора РЕАЛИЗОВАТЬ! | |
|
|
|
|
|
|
|
для: ZuArt
(23.03.2007 в 12:25)
| | да это-то все ясно... просто как-то глупо под каждую ленту новостей писать свой обработчик( ну или свое регулярное выражение | |
|
|
|
|
|
|
|
для: 1999
(23.03.2007 в 19:25)
| | Так и не надо!
Напишите одно универсальное рег. выражение и все! | |
|
|
|
|
|
|
|
для: ddhvvn
(23.03.2007 в 19:35)
| | гы) так тема-то как раз об этом))
вот вы можете написать ТАКОЕ универсальное выражение? | |
|
|
|
|
|
|
|
для: 1999
(23.03.2007 в 19:41)
| | Если разбирать RSS стандартными средствами анализа XML-документов (xml_parse_into_struct к примеру) таких проблем не возникает. | |
|
|
|
|
|
|
|
для: Trianon
(23.03.2007 в 19:56)
| | о... это интересно уже.. а по скорости как? будет уступать разбору регулярными или DOM'ом?
и не могли бы вы пример разбора написать? | |
|
|
|
|
|
|
|
для: 1999
(23.03.2007 в 20:01)
| |
<?php
include('config.inc.php');
function get_url($url)
{
$r = curl_init();
curl_setopt($r, CURLOPT_NOPROGRESS, 0);
curl_setopt($r, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($r, CURLOPT_URL, $url);
$res = curl_exec($r);
return $res;
}
$url = "http://news.yandex.ru/Russia/computers.rss";
$res = get_url($url);
// $f=fopen('computers.rss', 'wb'); fwrite($f, $res); fclose($f);die("ready");
// $res = file_get_contents("computers.rss");
// $x = simplexml_load_string($res); print_r($x);
function start_element($par, $name, $atr)
{
$tmp = array('data' => '', 'name' => $name, 'atr' => $atr);
global $heap; $l = ++$heap['level']; $lp = $l - 1;
$heap['stack'][$l] = $heap['ref'];
$heap['ref'] = array('data' => '');
if(!empty($atr)) $heap['ref']['atr'] = $atr;
}
function end_element($par, $name)
{
global $heap; $l = --$heap['level']; $ln = $l + 1;
$tmp = $heap['ref'];
$heap['ref'] = $heap['stack'][$ln];
unset($heap['stack'][$ln]);
$heap['ref']['sub'][$name][] = $tmp;
}
function element_data($par, $data)
{
global $heap;
if('' != trim($data))
$heap['ref']['data'].=iconv("utf-8", "windows-1251", $data);
}
$p = xml_parser_create("");
$heap['level'] = 0;
$heap['ref'] = array();
xml_set_element_handler($p, 'start_element', 'end_element');
xml_set_character_data_handler($p, 'element_data');
xml_parse($p, $res);
echo '<pre>';
print_r($heap);
|
| |
|
|
|
|
|
|
|
для: Trianon
(26.03.2007 в 19:20)
| | Вопрос в первую очередь к Trianon
Такая проблема вышла - нижнюю итоговую часть (начиная с xml_parser_create и заканчивая xml_parse) необходимо использовать внутри функции(( как ни извращался - $heap не виден функциям start_element итд. Пытался извратиться вобще так:
<?
class rss_feed
{
public $heap = array();
public $url;
public function __construct()
{
$this->rss_feed();
}
public function rss_feed()
{
$this->heap['level'] = 0;
$this->heap['ref'] = array();
}
// Загрузка фида через file_get_contents
public function load( $ext_url )
{
$this->url = file_get_contents( $ext_url );
}
// Загрузка фида через URL
public function load_through_curl( $ext_url )
{
$r = curl_init();
curl_setopt( $r,CURLOPT_NOPROGRESS,0 );
curl_setopt( $r,CURLOPT_RETURNTRANSFER,1 );
curl_setopt( $r,CURLOPT_URL,$ext_url );
$this->url = curl_exec( $r );
}
// Процессинг фида
public function process()
{
$p = xml_parser_create();
xml_set_element_handler( $p,"start_element","end_element" );
xml_set_character_data_handler( $p,"element_data" );
xml_parse( $p,$url );
echo "<pre>";
print_r( $this->heap );
}
private function start_element( $par,$name,$atr )
{
$tmp = array( "data" => "",
"name" => $name,
"atr" => $atr );
$l = $this->heap['level'] + 1;
$lp = $l - 1;
$this->heap['stack'][$l] = $this->heap['ref'];
$this->heap['ref'] = array( "data" => "" );
if ( !empty( $atr ) ) $this->heap['ref']['atr'] = $atr;
}
private function end_element( $par,$name )
{
$l = $this->heap['level'] - 1;
$ln = $l + 1;
$tmp = $this->heap['ref'];
$this->heap['ref'] = $this->heap['stack'][$ln];
unset( $this->heap['stack'][$ln] );
$this->heap['ref']['sub'][$name][] = $tmp;
}
private function element_data( $par,$data )
{
if( trim( $data ) != "" )
{
$this->heap['ref']['data'] .= iconv( "UTF-8","WINDOWS-1251",$data );
}
}
}
?>
|
но опять же - на выходе просто
<?
Array
(
[level] => 0
[ref] => Array
(
)
)
?>
|
почему? и если делать без объектов, то как сделать, чтоб функции start_element итд видели переменную $heap, которая уже находится внутри своей функции? | |
|
|
|
|
|
|
|
для: 1999
(01.04.2007 в 21:56)
| | . | |
|
|
|
|
|
|
|
для: 1999
(02.04.2007 в 00:11)
| | бьюсь как рыба об лед башкой и понимаю что я ламер страшный, раз такого не понимаю...
вот код теперь:
<?php
class rss_feed
{
public $feed_content;
public function __construct( $url )
{
$this->rss_feed( $url );
}
public function rss_feed( $url )
{
$this->feed_content = $this->load_through_fgc( $url );
}
// Загрузка через file_get_contents
private function load_through_fgc( $url )
{
$this->feed_content = file_get_contents( $url );
}
// Загрузка через CURL
public function load_through_curl( $url )
{
$r = curl_init();
curl_setopt( $r,CURLOPT_NOPROGRESS,0 );
curl_setopt( $r,CURLOPT_RETURNTRANSFER,1 );
curl_setopt( $r,CURLOPT_URL,$url );
$this->feed_content = curl_exec( $r );
}
// Процессинг фида
public function process()
{
global $heap;
$p = xml_parser_create();
xml_set_element_handler( $p,"start_element","end_element" );
xml_set_character_data_handler( $p,"element_data" );
xml_parse( $p,$url );
echo "<pre>";
print_r( $heap );
}
private function start_element( $par,$name,$atr )
{
global $heap;
$tmp = array( "data" => "",
"name" => $name,
"atr" => $atr );
$l = $heap['level'] + 1;
$lp = $l - 1;
$heap['stack'][$l] = $heap['ref'];
$heap['ref'] = array( "data" => "" );
if ( !empty( $atr ) ) $heap['ref']['atr'] = $atr;
}
private function end_element( $par,$name )
{
global $heap;
$l = $heap['level'] - 1;
$ln = $l + 1;
$tmp = $heap['ref'];
$heap['ref'] = $heap['stack'][$ln];
unset( $heap['stack'][$ln] );
$heap['ref']['sub'][$name][] = $tmp;
}
private function element_data( $par,$data )
{
global $heap;
if( trim( $data ) != "" )
{
$heap['ref']['data'] .= iconv( "UTF-8","WINDOWS-1251",$data );
}
}
}
$heap['level'] = 0;
$heap['ref'] = array();
$feed = new rss_feed( "http://news.yandex.ru/Russia/computers.rss" );
$feed->process();
?>
|
вроде и heap уже гломальна, но тем не менее воз и ныне там(( | |
|
|
|
|
|
|
|
для: 1999
(02.04.2007 в 20:51)
| | вот эти две строки
$heap['level'] = 0;
$heap['ref'] = array();
| снизу надо убрать.
А метод изменить так:
public function process()
{
global $heap;
$p = xml_parser_create();
xml_set_element_handler( $p,"start_element","end_element" );
xml_set_character_data_handler( $p,"element_data" );
$heap = array('level' => 0, 'ref' => array());
xml_parse( $p,$url );
echo "<pre>"; print_r( $heap ); // вместо этой строки нужно поставить код упрощения и переноса дерева в объект.
$heap = array();
}
|
Функции start_element, end_element и element_data из методов класса - выкинуть.
Поставить обычными функциями с глобальной областью видимости и временем жизни . | |
|
|
|
|
|
|
|
для: 1999
(02.04.2007 в 00:11)
| | бьюсь как рыба об лед башкой и понимаю что я ламер страшный, раз такого не понимаю...
вот код теперь:
<?php
class rss_feed
{
public $feed_content;
public function __construct( $url )
{
$this->rss_feed( $url );
}
public function rss_feed( $url )
{
$this->feed_content = $this->load_through_fgc( $url );
}
// Загрузка через file_get_contents
private function load_through_fgc( $url )
{
$this->feed_content = file_get_contents( $url );
}
// Загрузка через CURL
public function load_through_curl( $url )
{
$r = curl_init();
curl_setopt( $r,CURLOPT_NOPROGRESS,0 );
curl_setopt( $r,CURLOPT_RETURNTRANSFER,1 );
curl_setopt( $r,CURLOPT_URL,$url );
$this->feed_content = curl_exec( $r );
}
// Процессинг фида
public function process()
{
global $heap;
$p = xml_parser_create();
xml_set_element_handler( $p,"start_element","end_element" );
xml_set_character_data_handler( $p,"element_data" );
xml_parse( $p,$url );
echo "<pre>";
print_r( $heap );
}
private function start_element( $par,$name,$atr )
{
global $heap;
$tmp = array( "data" => "",
"name" => $name,
"atr" => $atr );
$l = $heap['level'] + 1;
$lp = $l - 1;
$heap['stack'][$l] = $heap['ref'];
$heap['ref'] = array( "data" => "" );
if ( !empty( $atr ) ) $heap['ref']['atr'] = $atr;
}
private function end_element( $par,$name )
{
global $heap;
$l = $heap['level'] - 1;
$ln = $l + 1;
$tmp = $heap['ref'];
$heap['ref'] = $heap['stack'][$ln];
unset( $heap['stack'][$ln] );
$heap['ref']['sub'][$name][] = $tmp;
}
private function element_data( $par,$data )
{
global $heap;
if( trim( $data ) != "" )
{
$heap['ref']['data'] .= iconv( "UTF-8","WINDOWS-1251",$data );
}
}
}
$heap['level'] = 0;
$heap['ref'] = array();
$feed = new rss_feed( "http://news.yandex.ru/Russia/computers.rss" );
$feed->process();
?>
|
вроде и heap уже гломальна, но тем не менее воз и ныне там(( | |
|
|
|
|
|
|
|
для: 1999
(01.04.2007 в 21:56)
| | > Такая проблема вышла - нижнюю итоговую часть (начиная с xml_parser_create и заканчивая
> xml_parse) необходимо использовать внутри функции(( как ни извращался - $heap не
> виден функциям start_element итд. Пытался извратиться вобще так:
Я в Вашем коде не нашел функций start_element, end_element, element_data. Нашел только методы. Методы и функции - разные вещи.
механизм xml_parse требует именно функций. Функциям этим негде взять контекст выполнения, кроме как из некоторой переменной с глобальной областью видимости.
Делать глобальным сам объект, передавая его в парсер, или оставить глобальной кучу результата, а потом обращаться к ней в конце разбора и переносить результат в объект - дело вкуса. Но некоторую глобальную сущность придется оставить - у функций разбора нет доп. параметра, через который передавался бы контекст выполнения. | |
|
|
|
|
|
|
|
для: Trianon
(02.04.2007 в 09:48)
| | эх... я даж вроде как примерно понял, но вот реализовать все ваши умные слова не могу((
может подскажете, где и что исправить, чтобы все работало?.. | |
|
|
|
|
|
|
|
для: Trianon
(02.04.2007 в 09:48)
| | . | |
|
|
|
|
|
|
|
для: 1999
(02.04.2007 в 19:30)
| | . | |
|
|
|
|
|
|
|
для: Trianon
(02.04.2007 в 19:50)
| | ну я реально не понимаю как сделать, чтобы эта $heap была видна в других местах(( | |
|
|
|
|
|
|
|
для: 1999
(02.04.2007 в 20:18)
| | global $heap;
Она не только должна быть видна в других местах. Она не должна являться членом(полем) класса. Впрочем, возможно её можно сделать ссылкой на такое поле. Но этого я не проверял. Собственно, если реентерабельность не требуется (не требуется разбирать в обдом скрипте два RSS-потока параллельно) то я не очень себе представляюю смысл всех этих ухищрений. | |
|
|
|