copysite

Те, кто хоть раз писал парсер, знает, что не стоит этого делать с помощью регулярных выражений. Проиллюстрировать это утверждение поможет следующий пример.

 Возьмем HTML код: 

<div><a href="http://xdan.ru"><div>Сайт по программированию парсеров</div><div> и многое другое</div></a></div>

К примеру, из него нам нужно получить описание и url сайта. Если брать исключительно этот кусок кода, то все решается достаточно просто: 

$html = '<div><a href="http://xdan.ru"><div>Сайт по программированию парсеров</div><div> и многое другое</div></a></div>';
preg_match('#<div><a href="([^"]+)"><div>([^<]+)</div><div>([^<]+)</div></a></div>#U',$html,$list);
echo 'url:'.$list[1].',title:'.$list[2].$list[3]; // выведет url:http://xdan.ru,title:Сайт по программированию парсеров и многое другое

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

<div><a href=”http://xdan.ru”><div>Сайт по <b>программированию</b> парсеров</div><div> и многое <div> многое </div> другое </div></a></div>

Такой код регулярному выражению не по зубам.

Обычно, в вузах на этот случай учат писать конечный автомат. Суть его в том, что мы перебираем, посимвольно, весь html текст, находим начало тега, и строим дерево документа. Так называемое DOM (Document Object Model)

Сейчас, писать такое самому  нет необходимости.

В php, начиная с  версии 5, есть встроенные методы работы с деревом документа (класс DOMDocument), но основан он на XML парсере.

А HTML и XML это хоть и очень похожие, но в тоже время абсолютно разные технологии.

К примеру, непременное требование к XML это закрытые теги и отсутствие ошибок.

Отсюда вытекает условие: ошибок в html, который мы парсим с помощью нативных средств php,  быть не должно.

К сожалению, на сайтах донорах, ошибки не редки, а значит этот метод отпадает.

Для корректного разбора таких сайтов, на помощь придут php библиотеки PHPQuery, Simple HTML DOM, Zend DOM Query, Nokogiri .

Некоторые из них, после небольших манипуляций скармливают html  тому же DOMDocument. Мы не будем их рассматривать.

В этой статье я расскажу про SimpleHTMLDOM. Этой библиотекой я пользуюсь уже несколько лет, и она меня еще ни разу не подводила.

Скачиваем последнюю версию здесь

Пусть Вас не смущает то, что она не обновлялась с 2008 года, то, что она умеет, полностью покроет Ваши нужды в разборе html текстов.

В архиве, который вы скачали, две папки (примеры работы и документация) и файл simple_html_dom.php.

simple_html_dom.php это и есть вся библиотека, больше ничего для работы не потребуется. Кидаем этот файл в папку с проектом и в своем скрипте просто подгружаем его.

include 'simple_html_dom.php';

Кроме документации, которую вы скачали с архивом, доступна еще online версия, ее  вы найдете здесь

Файл подключен и готов к работе.

Для того, чтобы начать разбирать HTML, его сперва нужно получить. Обычно, я делаю это при помощи библиотеки CURL.

В simplehtmldom есть методы для удаленной загрузки страниц.  После подключения файла библиотеки, нам доступны 2 функции для обработки HTML строк.

str_get_html(str) и file_get_html(url)

Они  делают одно и тоже, преобразуют HTML текст в DOM дерево, различаются лишь источники.

str_get_htm – на вход получает обычную строку, т.е. если вы получили HTML прибегнув к curl, или file_get_contents то вы просто передаете полученный текст этой функции.

$html = str_get_html('<html><body>Привет!</body></html>');

file_get_html – сама умеет загружать данные с удаленного URL или из локального файла

$html = file_get_html('http://www.yandex.ru/');

или

$html = file_get_html('data/test.htm');

К сожалению,  file_get_html загружает страницы обычным file_get_contents. Это значит если хостер, выставил в php.ini allow_url_fopen = false (т.е. запретил удаленно открывать файлы), то загрузить что-то удаленно, не получится. Да и серьезные веб сайты таким способом парсить не стоит, лучше использовать CURL с поддержкой proxy и ssl. Однако для наших опытов, вполне хватит и file_get_html.

$html = file_get_html('http://www.yandex.ru/'); 

в результате, в  переменной $html будет объект типа simple_html_dom.

При больших объемах данных, в библиотеке происходит утечка памяти. Поэтому после окончания одного цикла надо ее чистить.

Делает это метод clear.

К примеру грузим 5 раз сайт www.yandex.ru с разными поисковыми запросами

$k = 5; 
while($k>0){
 $html = file_get_html('http://yandex.ru/yandsearch?text=hi'.$k.'&lr=11114'); // загружаем данные
 // как-то их обрабатываем
 $html->clear(); // подчищаем за собой
 unset($html);
 $k--;
}

Эти две строчки $html->clear();  и unset($html);  лучше писать сразу же после того, как  Вы создали объект. Иначе забудете, и скрипт отвалится, забив всю память.

После того, как html текст упакован в объект, можно приступать непосредственно к поиску нужных элементов. 

Большинство поисковых функций выполняет метод find(selector, [index]).  Если второй аргумент не задан, метод возвращает массив элементов. Если же задан то элемент этого массива с индексом index.

Пример: скачаем главную страницу моего блога, и выведем все ссылки, которые встретим на своем пути.

require_once 'simple_html_dom.php';
$data = file_get_html('http://xdan.ru');
if($data->innertext!='' and count($data->find('a'))){
	foreach($data->find('a') as $a){
		echo '<a href="http://xdan.ru/'.$a->href.'">'.$a->plaintext.'</a></br>';
	}
}

В примере, в качестве селектора я воспользовался названием тега <a>. Но можно использовать и другие CSS селекторы. Элемент на странице можно найти по его атрибутам. В первую очередь, это название тега, id и class. Также могут быть использованы и второстепенные атрибуты, к примеру, href ссылки или width картинки. Если и этих атрибутов нет, то не грех воспользоваться и регулярными выражениями.

Поиск по названию тега вы уже видели

$html->find('div')

поиск по id

$html->find('#preview')

поиск по классу

$html->find('.myclass')

или комбинированный вариант

$html->find('#preview div.myclass')

в данном случае, сначала найдется элемент с id= preview затем в нем найдутся все теги div, и уже среди них фильтруются те у которых class=”myclass”

Если метод find ничего не нашел и index не задан, то он возвращает пустой массив. Если же index задан, то метод возвращает null.  

Поэтому верным решением будет проверить

if(count($html->find('#preview div.myclass')))
	foreach($html->find('#preview div.myclass') as $div)
		echo $div->innertext;

Поиск по наличию атрибута

$html->find(' img [width]'); // найдет нам все изображения у которых задан атрибут ширина

или более конкретный поиск по значению атрибута

$ret = $html->find('img[width=400px]');// найдет все изображения, у которых задана ширина равная 400px

Такая нотация позволяет искать по двум и более смежным классам

$ret = $html->find('img[class=active myclass]');//<img class="active myclass"/>

Поиск нескольких тегов

$html->find('a, img, br,span');

Поиск вложенных тегов

$es = $html->find('ul.myclass li');// найдет все li который является потомком ul(возможно и не прямым)
$es = $html->find('div.myclass li');// найдет все li в  div.myclass

У каждого найденного элемента также есть метод find

$html->find('div.myclass li');//найдет все div.myclass а потом все li лежащие в них

если нам нужно найти все li только первого div’а то мы можем написать так

$html->find('div.myclass',0)->find('li');

Поиск по значению атрибута не ограничивается только равенством. Вот доступные условия

[атрибут] – проверяет есть ли у элемента данный атрибут

[атрибут=величина] - проверяет, есть ли у элемента данный атрибут и равно ли его значение величине.( div[class=myclass] – найдет все div’ы у которых class равен myclass)

[атрибут!=величина] - проверяет, есть ли у элемента данный атрибут и не равно ли его значение величине.( div[class!=myclassok] – найдет все div’ы у которых class не равен myclassok)

[атрибут^=величина] - проверяет, есть ли у элемента данный атрибут и начинается ли его значение с величины ( div[class^=my] – найдет все div’ы у которых class начинается с my, к примеру myclass и myclassok)

 [атрибут$=величина] - проверяет, есть ли у элемента данный атрибут и заканчивается ли его значение величиной( div[class$=ok] – найдет все div’ы у которых class заканчивается на ok, к примеру myclassok, yok, okно не oki)

 [атрибут*=величина] - проверяет, есть ли у элемента данный атрибут и содержит ли его значение в себе величину, в любом месте(div[class*=sok] – найдет все div’ы у которых class содержит sok, к примеру myclassok, ysoki, sok)

Обычный текст можно искать как тег text

$es = $html->find('text'); // найдет все текстовые блоки в html

Комментарии находим по тегу comment

$es = $html->find('comment');

Каждый найденный элемент и сам $html имеют 5 полей

$html = str_get_html("<div>foo <b>bar</b></div>"); 
echo $html; // выведет <div>foo <b>bar</b></div>;
$e = $html->find("div", 0);
echo $e->tag; // Вернет: "div"
echo $e->outertext; // Вернет: <div>foo <b>bar</b></div>
echo $e->innertext; // Вернет: foo <b>bar</b>
echo $e->plaintext; // Вернет: foo bar

$e->tag            Читает или записывает имя тега элемента.

$e->outertext   Читает или записывает весь HTML элемента, включая его самого.

$e->innertext   Читает или записывает внутренний HTML элемента

$e->plaintext    Читает или записывает простой текст элемента, это эквивалентно функции strip_tags($e->innertext). Хотя поле доступно для записи, запись в него ничего не даст, и исходный html не изменит

$html = str_get_html("<div>foo <b>bar</b></div"); 
$div = $html->find('div',0);
$div->plaintext = 'gooo';
echo $div->innertext; // вернет <div>foo <b>bar</b></div>

Как  Вы могли догадаться, для удаления ненужного элемента из HTML можно затереть его поле  outertext

$html = str_get_html("<div>foo <b>bar</b></div"); 
$b = $html->find('b',0);
$b->outertext = '';
echo $html->innertext; // вернет <div>foo</div>

Тут следует помнить, что хоть элемент и не виден в html, из дерева DOM он никуда не делся

$html = str_get_html("<div>foo <b>bar</b></div"); 
$b = $html->find('b',0);
$b->outertext = '';
echo $html->innertext; // вернет <div>foo</div>, элемент удален из HTML
// но
echo count($html->find('b')); // вернет 1, в дерево элемент присутствует

при желании  мы даже можем вернуть элемент на место

$b->outertext = '<span>bar</span>';
echo $html->innertext;// вернет <div>foo<span>bar</span></div>

Для более эффективной навигации по дереву документа доступны методы

$e->children ( [int $index] )     Возвращает объект N-го прямого потомка, если индекс установлен, в противном случае возвращает массив всех дочерних элементов

$e->parent()    Возвращает родительский элемент.

$e->first_child() Возвращает первый дочерний элемент, или null, если ничего не найдено

$e->last_child() Возвращает последний дочерний элемент, или null, если ничего не найдено

$e->next_sibling() Возвращает следующий родственный элемент, или null, если ничего не найдено

$e->prev_sibling()       Возвращает предыдущий родственный элемент, или null, если ничего не найдено

пример

$html ="<div>
  <b>bar</b>
  <b>foo</b>
  <span>arg</span>
  <div>
    <b>tor</b>
  </div>
</div>"; 

Все дочерние элементы разные, как-то подобрать к ним селектор проблематично. Поэтому воспользуемся описанными методами.

$html  = str_get_html($html);
$div = $html->find('div',0);
$i = 0;
while($item = $div->children($i++)){
	echo $item->innertext;
} 

либо так

$item = $div->children(0);
echo $item->innertext;
while($item = $item -> next_sibling()){
   echo $item->innertext;
} 

Данные методы полезны при разборе таблиц, элементы которых, как правило, структурированы, но не имеют идентифицирующих атрибутов.

Ну и последняя фишка это вызов callback функции на найденный элемент

function my_callback($element) {
       if ($element->tag=='span')
                $element->outertext = '<b>'.$element->innertext. '</b>';// заменим все span элементы на b
} 
$html  = str_get_html('<span>bar</span><span>pole</span><span>sushi</span><a>okno</a>');
// Регистрация функции обратного вызова с ее именем
$html->set_callback('my_callback');// вызов функции произойдет при конвертации объекта в строку
echo $html; // на самом деле, при этом вызывается магический метод __toString, он и запускает наши калбяки

На экране мы увидим 

<b>bar</b><b>pole</b><b>sushi</b><a>okno</a>

 

Доступ к атрибутам элементов осуществляется напрямую

foreach($html->find('img') as $img) echo $img->src;
//или
echo $html->find('img',0)->src;

Хватит теории, перейдем к практике

Загрузим n фотографий из поисковой выдачи Yandex Картинок. http://images.yandex.ru/

require_once 'simple_html_dom.php';
// поисковый URL
$url = 'http://images.yandex.ru/yandsearch?text='.urlencode('Джессика Альба').'&rpt=image';
$n = 2;
// загружаем данный URL
$data = file_get_html($url);
// очищаем страницу от лишних данных, это не обязательно, но когда HTML сильно захламлен бывает удобно почистить его, для дальнейшего анализа
foreach($data->find('script,link,comment') as $tmp)$tmp->outertext = '';
// находим все изображения на странице
if(count($data->find('div.b-image img'))){
	$i = 1;
	foreach($data->find('div.b-image img') as $img){
		// выводим на экран изображение 
		echo '<img src="'.$img->src.'"/>';
		// и скачиваем его в файл
		file_put_contents('data/'.($i++).'.jpg',file_get_contents($img->src));
		if($i>$n)break; // выходим из цикла если скачали достаточно фотографий
	}
}
$data->clear();// подчищаем за собой
unset($data);

Как быть если нам нужно больше фото, чем лежит на одной странице?

Ответ прост: Код, приведенный выше, заключается в функцию, в html помимо фото находим еще  и URLвсех страниц, и рекурсивно вызываем данную функцию для этих страниц.

require_once 'simple_html_dom.php';
function getYandexImages($url,$findpages = true){
	static $i = 1;
	$n = 200;
	// загружаем данный URL
	$data = file_get_html($url);
	// очищаем страницу от лишних данных, это не обязательно, но когда HTML сильно захламлен бывает удобно почистить его, для дальнейшего анализа
	foreach($data->find('script,link,comment') as $tmp)$tmp->outertext = '';
	// находим URL страниц только для первого вызова функции
	if( $findpages and count($data->find('div.b-pager__pages a'))){
		foreach($data->find('div.b-pager__pages a') as $a){	
			// довольно распространенный случай - локальный URL. Поэтому иногда url надо дополнять до полного
			if( !preg_match('#^http://#',$a->href) )$a->href = 'http://images.yandex.ru'.$a->href;
			// и еще дна тонкость, & надо заменять на &
			$a->href = str_replace('&','&',$a->href);
			// вызываем функцию для каждой страницы
			getYandexImages($a->href,false);
		}
	}
	// находим все изображения на странице
	if(count($data->find('div.b-image img'))){
		foreach($data->find('div.b-image img') as $img){
			// выводим на экран изображение 
			echo '<img src="'.$img->src.'"/>';
			// и скачиваем его в файл
			file_put_contents('data/'.($i++).'.jpg',file_get_contents($img->src));
			if($i>$n)exit; // завершаем работу если скачали достаточно фотографий
		}
	}
	$data->clear();// подчищаем за собой
	unset($data);
}
// поисковый URL
$url = 'http://images.yandex.ru/yandsearch?text='.urlencode('Джессика Альба').'&rpt=image';
getYandexImages($url);

 

Все хорошо, 200 картинок лежат в папке data. Но их размер слишком мал.

Поэтому завершающим аккордом нашей практики будет загрузка увеличенной фотографии.

Для этого определим еще одну функцию

 

function getBigImage($url){
	$data = @file_get_contents($url);
	if(trim($data)=='')return false; // бывает что сайт недоступен, его фото мы не грузим
	$data = str_get_html($data);
	// находим фото
	if( count($data->find('#i-main-pic')) ){
		$dataimg = @file_get_contents($data->find('#i-main-pic',0)->src); // собачка нужна в если сервер нам вернул 404, это выозвет Warning:, поэтому экранируем ошибки
		if(trim($dataimg)=='')return false; // фото не доступно, его не грузим
		file_put_contents( 'data/'.md5($url).'.jpg', $dataimg ); // сохрпаняем в файл
	}
	$data->clear();// подчищаем за собой
	unset($data);
}

 

и слегка поправим getYandexImages

function getYandexImages($url,$findpages = true){
	global $i,$n;
	// загружаем данный URL
	$data = @file_get_contents($url);
	$data = str_get_html($data);
	// очищаем страницу от лишних данных, это не обязательно, но когда HTML сильно захламлен бывает удобно почистить его, для дальнейшего анализа
	foreach($data->find('script,link,comment') as $tmp)$tmp->outertext = '';
	// находим URL страниц только для первого вызова функции
	if( $findpages and count($data->find('div.b-pager__pages a'))){
		foreach($data->find('div.b-pager__pages a') as $a){	
			// довольно распространенный случай - локальный URL. Поэтому иногда url надо дополнять до полного
			if( !preg_match('#^http://#',$a->href) )$a->href = 'http://images.yandex.ru'.$a->href;
			// и еще дна тонкость, & надо заменять на &
			$a->href = str_replace('&','&',$a->href);
			// вызываем функцию для каждой страницы
			getYandexImages($a->href,false);
		}
	}
	// находим все изображения на странице
	if(count($data->find('div.b-image img'))){
		foreach($data->find('div.b-image a') as $a){
			if( !preg_match('#^http://#',$a->href) )$a->href = 'http://images.yandex.ru'.$a->href;
			$a->href = str_replace('&','&',$a->href);
			getBigImage($a->href);
			if($i++>=$n)exit; // завершаем работу если скачали достаточно фотографий
			echo '<script>document.getElementById("counter").innerHTML = "Загружено: '.$i.' из '.$n.' фото";</script>';
			flush();
		}
	}
	$data->clear();// подчищаем за собой
	unset($data);
}
// поисковый URL
$i = 1;
$n = 20; // будем грабить 20 картинок
$url = 'http://images.yandex.ru/yandsearch?text='.urlencode('Джессика Альба').'&rpt=image';
getYandexImages($url);

 

Вот и все, наслаждаемся фото великолепной Джессики Альбы. Надеюсь меня простит Яндекс, ведь по сути фото грабится не с их серверов, а с прямиком с сайтов, где они лежат.

Кроме того это всего лишь демонстрация работы. Думаю никому в здравом уме, не придет в голову парсить Яндекс с помощью file_get_content. Данную библиотеку можно применять и в мирном программировании. К примеру в качестве шаблонизатора для CMS. Почему нет, с хорошим кешированием будет очень удобная штука.

 При больших объемах сайтов доноров,  неплохо бы разбить все на потоки.

А используя описанный мой скрипт сортировки изображений по цвету, можно собрать неплохую отсортированную базу, фотографий знаменитостей.

И, как всегда, выкладываю все исходники

UPD: Благодаря пользователю Диме, выяснилось, что библиотека обновилась 2011-07-14 и имеет версию 1.5. Нововведений не много, однако самый главный баг, с которым сталкивались все, кто пользовался библиотекой, а именно утечка памяти, устранен. На то она и версия 1.5, а не 2.0. Радует, что проект все же поддерживается и развивается. Ждем новых релизов.

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

Комментарии  

Grisha
# Grisha 08.04.2011 04:09
Спасибо!!!
Игорь
# Игорь 01.05.2011 01:42
Вот скажем есть стр.:

http://cell-phones.shop.ebay.com/Cell-Phones-Smartphones-/3312/i.html?LH_BIN=1&_trkparms=65%253A10%257C66%253A4%257C39%253A1&rt=nc
&_dmpt=Cell_Phones&_ds=1&_fcid=168&_localstpos=&_sc=1&_sticky=1&_stpos=&_trksid=p3286.c0.m14
&gbr=1&_sop=15&_sc=1

Как спарсить картинки отдельно, описание отдельно, цену отдельно?
Leroy
# Leroy 03.05.2011 14:00
$site = 'http://cell-phones...=15&_sc=1';
$data = file_get_html($site);
foreach($data->find('#v4-56 table') as $table){
echo @$table->find('img',0)->src.'=>';
echo @$table->find('td.prc div.g-b',0)->plaintext.'=>';
echo @$table->find('div.ttl',0)->plaintext.'
';
flush();
}
$data->clear();
unset($data);


вродь все просто, откройте сайт в каком-нибудь DOM инспекторе и смотрите его структуру.

Встроенный дом инспектор есть в Опере,Хроме и IE начиная с 8 вродь. На файрфокс есть фаербаг.
Павел
# Павел 19.06.2011 05:07
"str_get_htm – на вход получает обычную строку" тут функция должна быть str_get_html
Павел
# Павел 19.06.2011 05:08
спасибо за статью
Иван
# Иван 16.07.2011 21:51
Здравствуйте, написал вот такой парс

$html = file_get_html("D:\Files\сайт\detail_ajax.htm");



foreach($html->find('script,link,comment') as $tmp)$tmp->outertext = '';

if(count($html->find('span[class="titleproductname]'))){

foreach($html->find('span[class="titleproductname] ') as $a){



print $title = $a->plaintext."
";





}

}



if(count($html->find('.textproductdescription'))){

foreach($html->find('.textproductdescription') as $a){



echo $a->innertext;





//при echo в цикле выводится все строки с дивов .textproductdescription

но когда присваеваю значение переменной, выводиться с переменной только одна строка, последняя



}

}

$image = $html->find('img',0)->src;

//echo $title, $text, $image;

$html->clear();

unset($html);

//подскажите как в цикле присвоить значение переменной?

или записать результат многих дивов?
Игорь
# Игорь 05.10.2011 00:43
Просто, спасибо!
Николай
# Николай 05.10.2011 16:42
Спасибо вам огромное...
Слава
# Слава 21.10.2011 04:43
foreach($data->find('div.b-pager__pages a')

что такое div.b-pager__pages a не могу разобраться
1341234
# 1341234 10.11.2011 01:58
блин. больше не статью читаю, а по бокам рисую. ни какой работы
Лариса
# Лариса 10.11.2011 16:54
А как делается такой фон? Оч забавно и ново. :) И читаешь и рисуешь одновременно
Олег
# Олег 17.01.2012 17:11
Очень полезная и интересная статья. Помогла реализовать мои идеи в кратчайшее время. Все в простой и доступной форме. Автору СПАСИБО.
serhey
# serhey 19.01.2012 04:41
да очень полезная статья !!!! Спасибо автору !!
Sleepwalker
# Sleepwalker 07.02.2012 16:05
// очищаем страницу от лишних данных, это не обязательно, но когда HTML сильно захламлен бывает удобно почистить его, для дальнейшего анализа

foreach($data->find('script,link,comment') as $tmp)$tmp->outertext = '';



Скажите, а здесь разве $data изменяется? разве изменения не происходят в локальной переменной $tmp ?
lerik
# lerik 07.02.2012 21:06
Для интереса попробуйте такой код
$g= array(1,2,3);
foreach($g as $j)
$j++;
print_r($g);
будете приятно удивлены
opozZzum
# opozZzum 07.08.2012 12:07
а разве не foreach($g as &$j) ?
Leroy
# Leroy 07.08.2012 21:07
опа это я ступил=) да вы правы именно так с &
Leroy
# Leroy 07.08.2012 21:08
тут немного ошибся, вообщем дело в том что сам $tmp как свойство сеодержит ссылку на некий объект который и изменяется, если мы будем менять сам $tmp то ничего не измениться, а вот если одно из его полей то изменения произойдут
Игорь
# Игорь 10.02.2012 03:37
Привет ребята. Я получил список ссылок с моего сайта такого типа:

1 -ссылка1

2 -ссылка2

1 -ссылка3

2 -ссылка4



что мне нужно дописать в коде, чтобы выводилось так:



1 -ссылка1

1 -ссылка2

1 -ссылка3

1 -ссылка4



у нужной мне ссылки нету атрибутов, для её поиска...

Заранее спасибо.
Svetlana
# Svetlana 20.02.2012 02:35
Спасибо, буду разбираться...



Ждем возвращения из армии!

Если, что надо пишите, вдруг сможем помочь!
Сергей
# Сергей 21.02.2012 21:01
не могу разобраться с загрузкой файлов



file_put_contents('data/'.($nomer).'.jpg',file_get_contents($img->src));



сохраняет нужное количество фалов в папке, но все они пустые

$img->src - содержит правильный путь к фото на сайте .. в чем беда не пойму :(
Сергей
# Сергей 21.02.2012 21:02
сам спросил, сам ответил :)

как только написал вопрос понял в чем проблема - оказывается в $img->src хранился относительный путь в фото, банально добавил название домена и все ок.



спасибо за помощь :) !
Stas
# Stas 02.03.2012 13:05
Добрый день!

Имеется следующий кусок кода:



Автор:А.Мецгер


ISBN:978-5-378-02142-0


Переплет:


Страниц:16


Формат:200х280



Со СПАНами все понятно, но нужно присвоить переменным значения,которые между тегами /strong и br или /strong и /span (для последнего случая)



Например:

MyAuthor = "А.Мецгер"

MyBinding = ""



Причем вся строка, например (ISBN:978-5-378-02142-0
) может отсутствовать.

Заранее благодарен.
Stas
# Stas 02.03.2012 13:10
Простите, заменяю текст



Добрый день!

Имеется следующий кусок кода:

{span class="block"}

{strong}Автор:{/strong}А.Мецгер{br}

{strong}ISBN:{/strong}978-5-378-02142-0{br}

{strong}Переплет:{/strong}{br}

{strong}Страниц:{/strong}16{br}

{strong}Формат:{/strong}200х280

{/span}

Со СПАНами все понятно, но нужно присвоить переменным значения,которые между тегами /strong и br или /strong и /span (для последнего случая)



Например:

MyAuthor = "А.Мецгер"

MyBinding = ""



Причем вся строка, например ({strong}ISBN:{/strong}978-5-378-02142-0{br}) может отсутствовать.

Заранее благодарен.
Димон
# Димон 18.04.2012 15:49
Супер! Молодчага что написал! Регулярка достает!
Антон
# Антон 10.06.2012 04:43
Нужен специалист для создания парсера и настройки переноса контента. Пишите на почту k-klient собак mail.ru
ygor
# ygor 12.06.2012 16:46
Что-то не пойму, как спарсить определённое значение скажем есть 1.txt файл с содержимым:

/pages/13674/1367437.shtml

/pages/14072/1407291.shtml

/pages/14107/1410773.shtml

/download.php?id=1420841.mp3

/reklama.shtml

/rp/list.php

/spages/events.shtml

Каким образом их этого файла выбрать имено строку: /download.php?id=1420841.mp3 ??? Спасибо заранее.
Leroy
# Leroy 12.06.2012 18:04
$data = explode("\r",file_get_contents('1.txt'));
foreach($data as $st){
if( preg_match("#\.mp3$#",$value) ){
echo $value.'
';
}
}


Я думаю тут все понятно) а вообще это элементарная работа со строками

P.S. Возможно что-то не работает, я только пришел с армии =)
Svetlana
# Svetlana 13.06.2012 03:04
С возвращением!!!
Leroy
# Leroy 13.06.2012 03:19
спасибо!)
ygor
# ygor 12.06.2012 18:47
Поздравляю с приходом))), Но действительно, не что-то, а вообще не работает (((
ygor
# ygor 12.06.2012 20:46
Да что такое, вообще запутался, ниче не выходит, пол дня бьюсь, может кто подскажет? бакс на кошелёк перечислю... Вот проблемма с выражением выше ничего не получилось. Даю прямой текст:

надо с этой страницы:

http://zaycev.net/pages/14208/1420841.shtml

выдрать ссылку **********.mp3 она одна там, выкладывайте вариант с Z Кошельком... СПС
Leroy
# Leroy 12.06.2012 21:28
элементарно

$data = file_get_contents('http://zaycev.net/pages/14208/1420841.shtml');
if( preg_match_all('#href="([^"]*\.mp3)"#Uis',$data,$list) )
print_r($list[1]);//в $list[1] будут все нужные нам ссылки со страницы
Александр
# Александр 21.06.2012 16:44
подскажите как выбрать элемент по класу если класов несколько через пробел?



....

Leroy
# Leroy 21.06.2012 17:12
Как вариант

$html = str_get_html('<div> <div class="div1">1</div>
<div class="div1">2</div>
<div class="div1 div2">3</div>
<div class="div1">4</div>
</div>');
$divs = $html->find('div.div1[class*=div2]');
Leroy
# Leroy 21.06.2012 17:21
ну или напрямую
$html->find('div[class=div1 div2]');
Александр
# Александр 21.06.2012 17:45
спасибо. еще вопрос метод clear вызывает ошибку

ErrorException [ Fatal Error ]: Allowed memory size of 134217728 bytes exhausted (tried to allocate 59008046 bytes)



фреймворк kohana
Leroy
# Leroy 21.06.2012 17:59
это не метод clear ее вызывает, а его не своевременный вызов. Где-то что-то не уничтожаете. Я писал про это
Виктор
# Виктор 24.06.2012 18:47
А вот у меня через полминуты выдает ошибку:

Fatal error: Maximum execution time of 30 seconds exceeded in simple_html_dom.php on line 70



Кстати, оригинальные примеры с Джессикой Альбой также не дорабатывают до конца, если увеличить количество выкачиваемого с 20 до, хотя бы, 500.
Leroy
# Leroy 24.06.2012 20:17
Знакомые грабли. Добавьте в начало скрипта эту строчку
ini_get('safe_mode') or set_time_limit(0);
и будет Вам счастье)
Виктор
# Виктор 25.06.2012 05:28
Всякий должен сам наступить на грабли! Спасибо - работает.
Викуля
# Викуля 29.06.2012 00:22
привет:)

парни, а совсем тугой можно помочь:)?

мне надо простейшую программульку -выдрать номера телефонов из одной категории сайта обьявлений.

никаких наворотов больше не надо - только голый текст с номерами тел. в столбик - шеф поручил составить такой список - я за день только 200 номеров собрала.

была бы очень благодарна за помощь:)
Leroy
# Leroy 29.06.2012 02:43
пиши на ящик, конешно помогу
Дима
# Дима 11.08.2012 01:00
обнови текст статьи- библиотека обновлена в 2011 году, если я правильно понял))
Миша
# Миша 26.08.2012 02:15
Спасибо, статья очень полезная
Евгений
# Евгений 30.08.2012 19:39
Имеется div вида


<div class="classname">
<p><strong>Текст</strong>: <strong>Текст</strong>.<br /><br /><strong>Текст</strong>: Текст<br /><strong>Текст</strong>: Текст<br /><strong>Жанр</strong>: Текст<br /><strong>Текст</strong>: Текст<br /><strong>Текст</strong>: Текст<br /><strong>Текст</strong>: Текст<br /><strong>Текст</strong>: Текст</p>
<p style="text-align: center;"><strong>Нужный текст1</strong></p>
<p style="text-align: center;"><iframe src="Нужная ссылка1" width="607" height="360" frameborder="0"></iframe></p>
<p style="text-align: center;">Нужный текст2</p>
<p style="text-align: center;"><iframe src="Нужная ссылка2" width="607" height="360" frameborder="0"></iframe></p>
<p style="text-align: center;"><strong>Нужный текст3</strong></p>
<p style="text-align: center;"><iframe src="Нужная ссылка3" width="607" height="360" frameborder="0"></iframe></p>
<p style="text-align: center;">Нужный текст4</p>
<p style="text-align: center;"><iframe src="Нужная ссылка4" width="607" height="360" frameborder="0"></iframe></p>
<p style="text-align: center;"><strong>Нужный текст5</strong></p>
<p style="text-align: center;"><iframe src="Нужная ссылка5" width="607" height="360" frameborder="0"></iframe></p>
</div>


Подскажите пожалуйста как распарсить и вывести нужный текст и соответствующую ему нужную ссылку. Всю голову сломал.
Leroy
# Leroy 30.08.2012 19:55
ну на вскидку примерно так
$data = str_get_html('код');
foreach($data->find('iframe') as $iframe){
echo $iframe->src.' '.$iframe->parent()->prev_sibling ()->plaintext.'<br>';
}
Евгений
# Евгений 30.08.2012 20:12
Спасибо!
Александр
# Александр 24.09.2012 15:10
Здравствуйте! Скачал ваши примеры, работает только один с ярлыками вашего блога. Пробовал спарсить по вашей инструкции спец предложения http://www.aviasales.ru/, ну не как не получается, страничка пустая все время.:(
Leroy
# Leroy 24.09.2012 17:10

Я ведь написал, что серьезные парсеры не пишутся через file_get_contents, нужно использовать curl


function request($url,$post = 0){
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url ); // отправляем на
curl_setopt($ch, CURLOPT_HEADER, 0); // пустые заголовки
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); // возвратить то что вернул сервер

curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); // следовать за редиректами
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30);// таймаут4
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_COOKIEJAR, dirname(__FILE__).'/cookie.txt'); // сохранять куки в файл
curl_setopt($ch, CURLOPT_COOKIEFILE, dirname(__FILE__).'/cookie.txt');
curl_setopt($ch, CURLOPT_POST, $post!==0 ); // использовать данные в post
if($post)
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
$data = curl_exec($ch);
curl_close($ch);
return $data;
}
echo request('aviasales.ru');


все отлично работает, почитайте эти статьи Авторизация на сайте при помощи curl php и Многопоточные парсеры
Александр
# Александр 24.09.2012 23:26
Спасибо за наводку, но признаюсь, мало что понял.

1. Обязательно нужна авторизация на сайте, что парсить данные?

2. Не понял тот пример что вы написали выше. Как он применим к моей ситуации.

Попробовал сделать следующим образом:

<? php

include_once('simple_html_dom.php');//подключаем библиотеку

//Инициализируем cURL-сессию
$ch = curl_init ("http://www.aviasales.ru/");

//открываем для записи файл yandex.txt
//сюда внесём исходный html-код
$fp = fopen ("avia.txt", "w");

//указываем куда копировать содержимое
curl_setopt ($ch, CURLOPT_FILE, $fp);

//Заголовок - не выводим
curl_setopt ($ch, CURLOPT_HEADER, 0);

//Поехали!
curl_exec ($ch);

//Закрываем cURL-сессию
curl_close ($ch);

//Закрываем дексриптор файла
fclose ($fp);

//И вставляем на страницу полученный код
include 'avia.txt';
?>


Можно как то по подробнее рассмотреть мою ситуацию?
Александр
# Александр 24.09.2012 23:29
Кстати как написано в статье сделать проверку PHP.ini на предмет включена cURL или нет. Сделал.



cURL support - enabled

cURL Information -libcurl/7.20.0 OpenSSL/0.9.8o zlib/1.2.3
Александр
# Александр 24.09.2012 23:39
Убрал:


include_once('simple_html_dom.php');//подключаем
библиотеку


пропала ошибка 500, с но все равно все пусто. Я если это проделать с yandex то парситься на ура! Подскажите что нужно сделать?:)
Leroy
# Leroy 25.09.2012 03:16
я проверил, мой пример выше работает прекрасно. Вам всего лишь нужно было сменить урл с aviasales.ru на http://www.aviasales.ru/specpredlozheniya-aviakompaniy и все заработает

авторизовыватся на сайте не нужно, дал линк на статью чтобы почитали про курл и общие принципы
Александр
# Александр 25.09.2012 10:04
Видимо я совсем не понимаю. В вашем примере нет
$url='aviasales.ru';


Значит нужно произвести замену в
echo request('aviasales.ru');
на
echo request('http://www.avi...aniy');
Правильно понял вас?

Я создал cookie.txt в той же директории где и лежит index.php, соответственно подправил путь:
curl_setopt($ch, CURLOPT_COOKIEFILE, dirname(__FILE__).'cookie.txt');


т.е. получается:
<? php
include_once('simple_html_dom.php');
function request($url,$post = 0){
$ch = curl_init();//здесь разве не нужно прописать адрес страницы для которой открывается сессия?
curl_setopt($ch, CURLOPT_URL, $url );//В вашем примере нигде не описана перменная $ur
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_COOKIEJAR,dirname(__FILE__).'/cookie.txt');
curl_setopt($ch, CURLOPT_COOKIEFILE,dirname(__FILE__).'cookie.txt');
curl_setopt($ch, CURLOPT_POST, $post!==0 );
if($post)
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
$data = curl_exec($ch);
curl_close($ch);
return $data;
}
echo request('http://www.aviasales.ru/specpredlozheniya-aviakompaniy'); //здесь мне вообще схема работы не понятна
?>


Но у меня все равно появляется сообщение с кодом 500. Честно говоря уже перечитал все не на раз. И хочу разобраться, но как то еще запутаннее получается.
Александр
# Александр 25.09.2012 10:15
Не верные пути указал в выше указанном файле в моем случае:

curl_setopt($ch, CURLOPT_COOKIEJAR,'cookie.txt');
curl_setopt($ch, CURLOPT_COOKIEFILE,'cookie.txt');
Leroy
# Leroy 25.09.2012 12:44
вы правильно поняли, нужно поменять именно там.

создавать cookie.txt не надо, он автоматически создастся, если сервере вернет куки

$ch = curl_init(); - адресс можно не прописывать, если он пишется ниже

curl_setopt($ch, CURLOPT_URL, $url );

в вашем коде в 15 строчке ошибка, нет слеша после dirname(__FILE__)

ошибка 500 возникает скорее всего потому, что в скрипте есть ошибка, а ваш сервер настроен на то чтобы не выдавать ошибок php, почитайте статейку как включить показ ошибок в php
Александр
# Александр 25.09.2012 14:44
Огромное спасибо! Сделал чтобы выводились ошибки по php, и исправил недочеты.:)

Очень благодарен!

А не подскажете дальше что изучать, чтобы вывести нужный мне контент, а не все в подряд?
Leroy
# Leroy 25.09.2012 15:03
эту статью)
Александр
# Александр 25.09.2012 15:55
Решил с простого вашего примера начать: Вывести контент с тегом "a".

Не могу понять что именно нужно вставить в $html = str_get_html('__________');

Пробовал и имя функции - request и $url, толку нет.

Вставлял после : return data;
Leroy
# Leroy 25.09.2012 16:00
str_get_html(request('http://xdan.ru'));

str_get_html - на вход принимает строку

file_get_html - на вход принимает url либо адрес файла
Александр
# Александр 25.09.2012 22:37
Спасибо, понял что не так делал. вот что у меня получилось:

?<?php
ini_get('safe_mode') or set_time_limit(0);
function request($url,$post = 0){
$ch = curl_init();
$url = 'http://www.aviasales.ru/';
curl_setopt($ch, CURLOPT_URL, $url );
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_COOKIEJAR,dirname(__FILE__).'/cookie.txt');
curl_setopt($ch, CURLOPT_COOKIEFILE,dirname(__FILE__).'/cookie.txt');
curl_setopt($ch, CURLOPT_POST, $post!==0 );
if($post)
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
$data = curl_exec($ch);
curl_close($ch);
return $data;
}

include_once('simple_html_dom.php');
$html = str_get_html(request('http://www.aviasales.ru/'));
if($html->innertext!='' and count($html->find('#holliday_prices'))){
foreach($html->find('#holliday_prices') as $blok){
echo $blok;
}
}
?>


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

 foreach($html->find('#holliday_prices') as $blok){...


Пробовал сделать следующее, но видимо не то:
$blok->find('a', 1)->href = 'www.test.ru';
Прошу очередной раз вашей помощи:)
Leroy
# Leroy 26.09.2012 12:45
наверно как-то так


foreach( $html->find('#holliday_prices a') as $a){
$a->href = str_replace('http://www.a..s.ru/','http://xdan.ru',$a->href);
}
echo $html->find('#holliday_prices',0)->innertext;
Александр
# Александр 26.09.2012 14:16
Спасибо, работает. Я сделал немного по другому:
if($html->find('#holliday_prices')){
foreach($html->find('#holliday_prices') as $blok){

}
}

$newurl = "http://test.ru/";
echo preg_replace('#(\<a[^\>]*href\=\")(.*?)(\"\>)#', "$1{$newurl}$3", $blok);


Сделал так, потому что ваш вариант работает только с конкретной ссылкой:)Теперь надо понять, как это дело украшать)
Leroy
# Leroy 26.09.2012 14:32
остается понять, что вы делаете на этой странице, раз все равно используете регулярки =)
Александр
# Александр 26.09.2012 16:15
Честно говоря, просто свое решение я нашел раньше и решил его отобразить здесь. Но пытаюсь понять как сделать это не через регулярки. PHP я только начинаю изучать, поэтому может получается каша в коде:)Кстати, вам бы форум бы сделать, где можно было бы обсуждать статьи и свои скрипты на основе их:)
Александр
# Александр 26.09.2012 16:22
А как с вами можно связаться? просто аська указанная в вашем профеле, принадлежит другому человеку.
Денис
# Денис 25.09.2012 05:53
Отличная статья, спасибо! Все что нужно оговорено. Пишите еще.
Евгений
# Евгений 25.09.2012 11:43
Данная статья была для меня крайне полезна, спасибо автору.

Когда задавал вопрос, подписался на уведомления о комментариях, но как теперь отписаться?
Leroy
# Leroy 25.09.2012 12:05
развиваю движок, извините за неудобство. Сейчас добавлю такой функционал
Leroy
# Leroy 25.09.2012 12:22
хотя нет соврал, есть такая возможность, напишите комент и уберите галочку Подписаться на уведомления о новых комментариях
Leroy
# Leroy 25.09.2012 13:45
теперь есть такая возможность, хотя вы наверно уже отписались
qazarius
# qazarius 01.10.2012 05:08
Спасибо

Кажется помогло
Александр
# Александр 26.09.2012 16:51
А вы можете написать про кодировку?

Вот такая ситуация:

У меня CMS на win1251, а сайт донер на UTF8, парсинговый скрипт соответственно пишется в кодировке UTF-8. Как только этот скрипт подгружаю на сайт в нужное место, весь спарсенный контент появляется ввиде символов. Как сделать так чтобы Данные нормально отображались и при кодеровке win1251&
Leroy
# Leroy 26.09.2012 17:02
$text = iconv('utf-8','windows-1251',$text);


работает не всегда, т.к. многих символов в win, которые есть в utf, попросту нет.

еще есть mb_convert, загуглите

еще на php.net под описанием iconv куча велосипедных реализаций, если iconv не справляется то попробуйте их, по опыту скажу, что 100% рабочего решения вы не найдете, у каждого сайта свои тонкости. Это та еще проблемка
Jeka
# Jeka 29.09.2012 01:14
Прочитал первые несколько слов, сразу захотелось выразить несогласие, с помощью регекспов можно распарсить разметку любой сложности, если уметь ими пользоваться. ИМХО
Leroy
# Leroy 30.09.2012 22:49
уверяю вас, не любой, пользовался регэкспами до знакомства с этой библиотекой, самые проблемы возникают когда разметка у одной и той же страницы различается в зависимости от контента, никакие регэкспы не помогут если при заполнении юзер может сам вводить произвольные теги в содержание, тогда только dom
levarm
# levarm 04.10.2012 21:28
Подскажите как персить текст группируя по class: ico-phone, ico-ICQ, ico-adress сложность заключается в том что эти элементы стоят в span перед нужным для персинга текстом.

<div class="padB10 wrapMargin">
<div class="wrapIcons"><span class="ico-set ico-phone"></span>9131258 </div>
<div class="wrapIcons"><span class="ico-set ico-phone"></span>(846) 248-32-02 </div>
<div class="wrapIcons"><span class="ico-set ico-ICQ"></span>571-524-990</div>
<div class="wrapIcons"><span class="ico-set ico-adress"></span> Адрес предприятия</div>
</div>
Leroy
# Leroy 04.10.2012 21:50

$data = str_get_html('код');
foreach($data->find('ico-phone,ico-ICQ,ico-adress') as $item){
// 1 вариант
echo $item->next_sibling()->innertext; // не уверен, что сработает
// 2 вариант
echo $item->parent()->innertext; // если все как в вашем примере
// 3 вариант
$item->parent()->find('ico-phone,ico-ICQ,ico-adress',0)->outertext = '';
echo $item->parent()->innertext;
}
// 4 вариант
foreach($data->find('wrapIcons') as $item){
echo $item->innertext;
}


не один из вариантов не проверял, и думаю кусок кода вы привели для примера, но думаю ход мыслей понятен
Bane
# Bane 16.10.2012 17:18
Спасибо автору! Начал знакомство с парсерами с этой статьи. Теперь могу парсить практически все.
serg
# serg 01.11.2012 03:42
А как отсюда спарсить title и саму картинку, да еще и 2 слэша мешают((

<img class="lazy" title="testing image" data-src="//test.com/img/test.img" />
Leroy
# Leroy 01.11.2012 13:00
подобные вещи типа echo $a->src; делаются через "магические" методы php, т.е. эта запись эквивалентна echo $a->__get('src'); а в вашем случае будет echo $a->__get('data-src');, однако чтобы в эти дебри не углубляться у библиотеки есть стандартные методы getAttribute и setAttribute эквивалентные javascript'ским
$img = str_get_html('<img class="lazy" title="testing image" data-src="//test.com/img/test.img" />');
echo str_replace('//','/',$img->getAttribute('data-src'));
IgorA100
# IgorA100 03.11.2012 17:00
Добрый день.

Столкнулся с проблемой кодировки :(

Есть страница: http://beward.ru/goods/?dir1=1&dir2=14 в кодировке "windows-1251"



Есть рабочая ф-ция


function curl_gets_NEW($url){
$ch = curl_init();

$allUseragents = array(
"Opera/9.23 (Windows NT 5.1; U; ru)",
"Mozilla/16.0.1 (compatible; MSIE 5.12; Mac_PowerPC)",
"Opera/8.54 (Windows NT 5.1; U; ru)",
"Opera/9.21 (Windows NT 5.0; U; ru)",
"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.0.3705; .NET CLR 1.1.4322; Media Center PC 4.0; .NET CLR 2.0.50727)",
"Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; 3305; Wanadoo 6.1)",
);

$agent = $allUseragents[array_rand($allUseragents)];
curl_setopt_array($ch, array(
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => 1,//return data as string
CURLOPT_CONNECTTIMEOUT => 10,//timeout
CURLOPT_TIMEOUT => 100,
CURLOPT_USERAGENT => $agent,
CURLOPT_HEADER => 0,
CURLOPT_NOPROGRESS => 0,
CURLOPT_FAILONERROR => 0,
CURLOPT_FOLLOWLOCATION => 0,
CURLOPT_SSL_VERIFYPEER => 0,
)
);


$data = curl_exec($ch);
curl_close($ch);
return $data;
}


Читаем:

$url = 'http://beward.ru/goods/?dir1=1&dir2=14';

$content = curl_gets_NEW($url);

Все нормально!

Далее, читаем: $HTMLtext = str_get_html($content,true,true,'windows-1251');

и получаем вместо русских букв пустоту :(

Если не указывать кодировку при "str_get_html", то появляется белеберда.

mb_detect_encoding тоже не помогает. Вообще вошел в ступор :(
Lucky_7
# Lucky_7 04.11.2012 11:01
Вы в какой кодировке работаете-то? Надо все привести к общему знаменателю - то есть если ваш скрипт и база работают с UTF-8, то вам надо результаты парсинга сконвертировать в UTF-8. Тут поможет iconv().

А вообще я бы советовал работать с чистым DOMDocument через xpath без использования дополнительных библиотек.
IgorA100
# IgorA100 04.11.2012 16:56
Работаю в win-1251

Про приведение к единой кодировке я в курсе, но ни iconv(), ни mb_detect_encoding() не помогали.

Все оказалось банально просто, сайт говорит что кодировка win-1251, а реально контент на нем в win-1252.
Виталий
# Виталий 28.11.2012 10:05
В общем есть сайт-http://auctions.a-automarket.com/auctions/?p= project/searchform&s&ld при авторизации выдаёт форму поиска, так вот эту форму нужно встроить в свой сайт. Как это реализовать? Узал simplehtmldom_1_5, но так и не разобрался как зайти на закрытую страницу средствами php( Нашел «lxml» библиотеку для парсинга, но не знаю есть ли смысл тратить время на её изучение...В общем был бы благодарен за помощь, а если конкретно укажите что и как делать готов материально поблагодарить)
Leroy
# Leroy 28.11.2012 15:27
все тоже самое что и обычный парсинг, за исключением того что сперва нужно авторизоваться
Максим
# Максим 29.11.2012 21:21
Подскажите пожалуйста. есть такой HTML




<dl class="catalog">
<dt>
<dd>
<dd>
<dd>
</dl>




В тэгах есть еще вложенные , это я скопировал не раскрыв их.



Мне нужно занести в массив, делаю так:


$cat = $data->find('.catalog dd');




И в $cat добавляются все тэги и вложенные все, а мне надо только которые первые, не глубже. Как можно это сделать?
Leroy
# Leroy 30.11.2012 13:02
в топике есть примеры перебора дочерних элементов, либо методом children либо методом next_sibling
Dexel
# Dexel 03.12.2012 23:28
Загрузка обеих процессоров под 100% при выполнении команды str_get_html(str)

Может из-за того, что страница перекодирована из win1251 в UTF-8
Leroy
# Leroy 04.12.2012 13:45
может просто страничка большая?
Никита
# Никита 07.12.2012 02:19
Как перекодировать полученные данные с сайта, который на utf-8, так как при выводе у себя (cp1251) фрагмент с кирилицей "169 р." отображается как "169 СЂ."



iconv не работает
Leroy
# Leroy 07.12.2012 13:21
перевод из большей кодировки в меньшую вообще сопряжен с такими вещами, потому как в cp1251 тупо меньше букавак, панацею я не нашел, каждый раз помогал определенный конвертер. Искать их стоит в комментах к iconv на php.net
Алексей
# Алексей 19.12.2012 12:06
Отличная статья.

Автору спасибо. Как раз необходим был хороший пример помимо мануала.

Я в парсинге новичок, но появилась такая необходимость.

Подскажите, как правильно организовать парсер новостных сайтов. Я так понимаю, делать это с сервера, на котором расположен сайт агригатор не стоит?
Leroy
# Leroy 19.12.2012 13:23
ну вообще можно и сделать почему нет. Новостники вряд ли имеют сколько нибудь сильную защиту. Обычно он почти все через рсс выдают, грабь не хочу. Даже эта либа не нужна
naut
# naut 02.01.2013 21:41
Привет, Друзья!

Всех с Новым годом! Ура!

Помогите, запутался, не пойму что не так (новичёк-самоучка, что с меня взять))).

Вопрос в следующем.

Извлек страницу, распарсил этой чудной библиотекой, на экран все выводится в лучшем виде, но при записи в файл (стоит задача сохранить в один файл все ссылки) получается не 1 файл со списком N-ссылок, а N-файлов с ОДНОЙ каждой последующей ссылкой. Уже всякие варианты перебрал, менял циклы всякие, получается либо последняя ссылка в одном файле, либо как уже описал. Вот кусок кода где происходят итерации (подскажите ошибку):



$html= str_get_html($str);

$n = count($html->find('a, href'));

foreach($html->find('script,comment,image,img, png, jpg') as $tmp)$tmp->outertext = '';

if(count($html->find('a'))){

$i=0;

foreach($html->find('a') as $links){

echo $links->href .' ('. $links->innertext. ')
';

$result = file_put_contents(($i++).'Links.txt', $links->href);

if($i==$n)break;





if ($result) echo 'Данные в файл успешно занесены.';

else echo 'Ошибка при записи в файл.';



Нурбол
# Нурбол 20.02.2013 20:02
Здравствуйте

какой код тут надо сделать что бы взять цифры с 246.62 и 4.87 по отдельности в массив

Coğrafi Kuzeyden Kıble Açısı : 246.62 ° dir

2013 Senesi Ortası İçin Sapma Açısı : 4.87 ° dir

Pusula Kuzeyine Göre Kıble Açısı : (246.62) - (4.87) = 241.75 ° dir.
Leroy
# Leroy 20.02.2013 20:12
if(preg_match_all('#[\d]+\.[\d]+#',$text,$list))
foreach($list as $dig)
echo $dig;


Учите регулярные выражения, хоть я и написал что только с помощью них парсить нельзя, но и совсем без них парсить сложновато
Нурбол
# Нурбол 21.02.2013 12:08
Parse error: syntax error, unexpected T_VARIABLE, expecting T_PAAMAYIM_NEKUDOTAYIM in Z:\home\parser\www\inde1x.php on line 5

пишет!

2 дня перечитал все не получается! тестирую на денвере!

http://www.namazvakti.com/QAbout.php?cityID=8408 сайт откуда нужно взять 246.62 и 4.87

помогите пожалуйста! в долгу не останусь!
Leroy
# Leroy 21.02.2013 12:20
ну вы хоть код приведите, я же не телепат. Мой код я проверял, он работает
Нурбол
# Нурбол 21.02.2013 12:33


include('simple_html_dom.php');



$html = file_get_html('http://www.namazvakti.com/QAbout.php?cityID=8408');



if(preg_match_all('#[\d]+\.[\d]+#',$text,$list))

foreach($list as ­$dig)

echo $dig;
Leroy
# Leroy 21.02.2013 12:57
$html = file_get_contents('http://www.namazvakti.com/QAbout.php?cityID=8408');
if(preg_match_all('#[\d]+\.[\d]+#',$html,$list))
print_r($list[0]);
не понятно только, зачем вам simple_html_dom
Нурбол
# Нурбол 21.02.2013 13:29
Вопрос решили спасибо сайту! буду заходить и поставлю в закладки)
Илья55
# Илья55 25.02.2013 21:46
Подскажите по simple_html_dom. Пробую простые парсеры.

Например:



include_once('C:/Users/Public/Apache/htdocs/Parser/simple_html_dom.php');

echo file_get_html('http://www.yandex.ru/')->plaintext;



Ругется:



PHP Fatal error: Call to undefined function mb_detect_encoding() in C:\Users\Public\Apache\htdocs\Parser\simple_html_d om.php on line 1234
Leroy
# Leroy 25.02.2013 22:29
у вас не установлена библиотека php_mbstring.dll, поэтому и не доступна функция mb_detect_encoding. В php.ini нужно добавить строку extension=php_mbstring.dll ну и соответствующая dll должна лежать в папке с расширениями php
Илья55
# Илья55 25.02.2013 23:11
Да, включил в php.ini extension=php_mbstring.dll.

Ну а сам php_mbstring.dll у меня лежит в C:\Program Files\PHP\ext, я так думаю это верно.



Подскажите а почему выводятся кракозябры типа:

Секс знакомства ru -

после парсинга
Leroy
# Leroy 25.02.2013 23:32
кодировка отличается, ваша и сайта донора
Илья55
# Илья55 27.02.2013 18:21
А где это можно исправить,не подскажите?
Leroy
# Leroy 27.02.2013 18:24
в настройках браузера)
wolflingsu
# wolflingsu 13.05.2013 00:16
Полезно обрабатывать полученный HTML перед его парсингом. В том числе и кодировки:




function prepareForDOM($html, $encoding) {
$html = iconv($encoding, 'UTF-8//TRANSLIT', $html);
$html = preg_replace('/<(script|style|noscript)\b[^>]*>.*?<\/\1\b[^>]*>/is', '', $html);
$tidy = new tidy;
$tidy_config = array(
'drop-font-tags' => true,
'drop-proprietary-attributes' => true,
'hide-comments' => true,
'indent' => true,
'logical-emphasis' => true,
'numeric-entities' => true,
'output-xhtml' => true,
'input-encoding' => 'utf8',
'output-encoding' => 'utf8',
'wrap' => 0
);

$tidy->parseString($html, $tidy_config, $tidy_config['output-encoding']);
$tidy->cleanRepair();
$html = $tidy->value;
$html = preg_replace('#<meta[^>]+>#isu', '', $html);
$html = preg_replace('#<head\b[^>]*>#isu', "<head>\r\n<meta http-equiv='Content-Type' content='text/html; charset=utf-8' />", $html);

return $html;
}
Leroy
# Leroy 13.05.2013 11:10
осталось только узнать что за класс tidy
wolflingsu
# wolflingsu 14.05.2013 12:55
Leroy, вы шутите? =)

http://www.php.net/manual/ru/book.tidy.php
Илья55
# Илья55 25.02.2013 22:22
Опечатка в Илья55 25.02.2013 18:20: включил extension=php_mbstring.dll а не extension=php_ldap.dll
Илья55
# Илья55 25.02.2013 22:52
Подскажите почему при парсинге некоторых сайтов, например yandex,при:



include_once('C:/Users/Public/Ap­ache/htdocs/Parser/si­mple_html_dom.php');

echo ­­file_get_html('http://www.yandex.ru/')->plaintext;



пишет стандартное сообщение:



Этот веб-узел не может отобразить эту страницу

HTTP 500

Возможные причины:

Веб-узел находится в состоянии обслуживания.

На этом веб-узле обнаружена программная ошибка.



Попробуйте сделать следующее:

Повторите ввод адреса.



Перейдите на предыдущую страницу.



Подробнее



Эта ошибка (HTTP 500 - внутренняя ошибка сервера) означает, что на веб-узле, который вы хотите посетить, имеется проблема, препятствующая отображению нужной веб-страницы.



Тое есть у этих сайтов стоит защита от парсера?
Leroy
# Leroy 25.02.2013 22:57
т.е. серьезные сайты не стоит парсить file_get_html (который использует file_get_content), используйте cUrl а уже потом результат распарсивайте str_get_html
Илья55
# Илья55 25.02.2013 23:00
Спасибо Leroy, уже читаю про cUrl
Stan
# Stan 28.02.2013 21:59
Подскажите, как спарсить со страницы Base64, что б обрезало весь текст и теги, оставался чистый Base64, буду очень благодарен
Leroy
# Leroy 01.03.2013 11:06
ну чисто теоретически base64 то набор букв и цифр некой длинны, чаще всего это длинна будет большая. Поэтому тут легко справится что-то вроде
if(preg_match_all('#[a-zA-Z0-9]{10,}[=]?#',$data,$result))
print_r(result);
Stan
# Stan 01.03.2013 18:26
Спасибо за быстрый ответ! Буду пробывать :)

Отлично написали статью, с нее начал знакомиться с парсингом.
Федор
# Федор 02.04.2013 23:32
Добрый день!

Есть задачка:


$o = str_get_html('<a class="some class" onclick="return {"var1":{"var2":"val"},"var3":{}}" href="/some/href/">Text</a>');

var_dump($o);//["attr"]=> array(2) { ["class"]=> string(10) "some class" ["onclick"]=> string(8) "return {" }




Лажа в том, что атрибут href для ссылки получить не удастся... По идее все портит json, но как это обойти?

Есть идеи?
Leroy
# Leroy 03.04.2013 02:33
хоть я и написал, что регулярки применять для распарсивания DOM не стоит, для строк лучше их не найти. preg_match('#href="([^"]+)"#',$data,$list) вот и все
Guest
# Guest 08.05.2013 15:51
Спасибо! Отличный мануал! Так же порадовал котейка, который просит отключить AdBlock - на мне сработало :)
grarnik
# grarnik 14.05.2013 15:56
Спасибо. Помог)
Comeonandroid
# Comeonandroid 23.05.2013 08:26
Помогите, никак не могу заставить работать ваш парсер в нынешних условиях. Получилось скачать 30 картинок подставив нужные теги div.b-images-item__wrap img вместо div.b-image img, но вот получить ссылку на дальнейший поиск никак не удается, я нашел её в исходном коде, она в этом элементе если жать на неё из браузера со страницы исходного кода все нормально, но как я не пробовал запихнуть её в парсер следуя инструкциям ничего ен получается
nisampurger
# nisampurger 26.05.2013 17:53
у меня есть xml файл вот с таким содержанием:



...



...



как получить с помощью Simple HTML DOM значения атрибутов Code, HighPic, Title?

Заранее благодарен :)
nisampurger
# nisampurger 26.05.2013 17:56
...



...
nisampurger
# nisampurger 26.05.2013 17:57
...

Product Code="1" HighPic="namepic.jpg" Title="titleproduct"

...
Евгений
# Евгений 24.06.2013 10:33
Здравствуте, совсем новичок в php

Подскажите, взял такой скрипт:


require_once 'simple_html_dom.php';
$data = file_get_html('http://turbo-tor.com/all-foto-rewievs/');
if($data->innertext!='' and count($data->find('.entry-content a img'))){
foreach($data->find('.entry-content a img') as $b){
echo '<a href="" rel="rr" onclick="return jsiBoxOpen(this)" title="">'.$b.'</a>';
}
}


Хочу в htef="" подставить адрес картинки, но у меня не выходит.

Не могу правильно составить поиск и вытянуть в href.

Как правильно это сделать?

Спасибо.
Leroy
# Leroy 24.06.2013 11:35
ну у img нет href, у него есть только src
echo '<a href="'.$b->src.'" rel="rr" onclick="return jsiBoxOpen(this)" title="">'.$b.'</a>';
Евгений
# Евгений 25.06.2013 00:02
сорри, неправильно выразился, в $b сама картинка, отлично выводится,

нo в href мне надо поместить не src img, а адрес ссылки в которую заключен сам тег img.

тоесть парсю вот это:

<a href="http://turbo-tor.com/wp-content/uploads/2013/06/1212.png"  data-slb-group="240" data-slb-active="1" data-slb-internal="0">
<img class="alignnone size-medium wp-image-222" alt="1212" src="http://turbo-tor.com/wp-content/uploads/2013/06/1212-300x232.png" width="300" height="232"/>
</a>


просто примеров не нашол, либо не внимательно смотрел, как высунуть в одном цыкле вывести две переменные и подставиь их.

Получаеться img есть, а как второй парсинг подставить и правильно вытянуть, не могу.



Leroy
# Leroy 25.06.2013 03:30
невнимательно читали

$b->parent() Возвращает родительский элемент.

$b->parent() ->href
Евгений
# Евгений 25.06.2013 08:09
Огромное спасибо!
doctor
# doctor 01.07.2013 21:26
Подскажите пожалуйста, а как парсить разные значения и забивать их в массив, т.е. span class=today и span class=wday в массив с ключем 1, а все остальное к примеру td class=time, так как первые меняются, а последующие повторяются?
Leroy
# Leroy 02.07.2013 00:59
ничего не понял
doctor
# doctor 02.07.2013 08:06
Вот код для примера:

<span class=today>Понедельник 22 июня</span><td class=time>11 ч.</td><span class=wday>Вторник 23 июня</span><td class=time>12 ч.</td>


значения span с классами today, wday нужно найти и поместить в:

$arr_info[0][$i]


значения td с классом time нужно найти и поместить в:

$arr_info[1][$i]
Leroy
# Leroy 02.07.2013 11:46
$i = 0;
foreach($data->find('span.today') as $today){
$arr_info[0][$i] = $today->innertext;
$arr_info[1][$i++] = $today->next_sibling()->innertext;
}
Ibo_Sher
# Ibo_Sher 08.07.2013 16:54
Добрый день подскажите как передать в парсер класс, если его имя содержит пробел? Нпример
Leroy
# Leroy 08.07.2013 17:07
я писал об этом a[class=class1 class2]
Парсер
# Парсер 04.01.2015 21:50
Класс не может содержать символа пробела.

Можно искать по одному из классов которые прописаны в атрибуте class.

К примеру


<a href="#" class="class1 class2">Some link</a>

можно найти


$dom->find('a.class1', 0);
Виталий
# Виталий 16.07.2013 06:27
Добрый день, встретился с такой проблемой - есть сайт с таблицей в 1й колонке идут картинки, во второй артикул, в третьей текст, необходимо парсить только те картинки у которых во второй колонке идентичный артикул. До этого не занимался подобными вещами, но тут иначе ни как. Уже голова квадратная от всего этого... Буду признателен за помощь!
Leroy
# Leroy 16.07.2013 11:43
$today->next_sibling() $today->prev_sibling()
Виталий
# Виталий 17.07.2013 05:48
Благодарю)
Андрей
# Андрей 29.07.2013 03:22
Спасибо за статью.

Но тем не менее столкнулся с проблемой:

Пробуем парсить html:


<html>
<head>
<title>Тексты песен. Слова к песням, скачать бесплатно музыку в mp3</title>
<meta name="description" content="база текстов песен, слова к песням исполнителей музыки" />
<meta name="keywords" content="тексты песен, текст песни, слова к песне, скачать бесплатно" />
<meta http-equiv=Content-Type content="text/html;charset=windows-1251" />
<meta http-equiv="content-language" content="ru" />
</head>
<body>

<div align="center">

</div>


</body>
</html>




Для этого использую:


function prepareForDOM($html, $encoding) {
$html = iconv($encoding, 'UTF-8//TRANSLIT', $html);
$html = preg_replace('/<(script|style|noscript)\b[^>]*>.*?<\/\1\b[­^>]*>/is', '', $html);
$tidy = new tidy;
$tidy_config = array(
'drop-font-tags' => true,
'drop-proprietary-attributes' => true,
'hide-comments' => true,
'indent' => true,
'logical-emphasis' => true,
'numeric-entities' => true,
'output-xhtml' => true,
'input-encoding' => 'utf8',
'output-encoding' => 'utf8',
'wrap' => 0
);

$tidy->parseString($html, $tidy_config, $tidy_config['output-encoding']);
$tidy->cleanRepair();
$html­= $tidy->value;
$html = preg_replace('#<meta[^>]+>#isu', '', $html);
$html = preg_replace('#<head\b[^>]*>#isu', "<head>\r\n<meta http-equiv='Content-Type' content='text/html; charset=utf-8' />", $html);

return $html;
}

$answer_m = file_get_contents('newhtml.html');
$answer_m = prepareForDOM($answer_m, 'cp1251');
$html = str_get_html($answer_m);
$lets = $html->find('div');




Два момента интересны:

1. Если не заменять(закоментить prepareForDOM) то выдает ошибку

arning: mb_strpos() [function.mb-strpos]: Offset not contained in string ... on line 1570



2. Даже после предварительной обработки div не находится. $lets - пустая на выходе.



Очень надеюсь на вашу помощь. Сам уже и не знаю что делать - на другую библиотеку что-ли переходить...
Андрей
# Андрей 29.07.2013 10:41
1. - так и не понятно почему так

2. если убрать элемент русский текст из title, то работает нормально, даже если русский текст есть в теле страницы.
Leroy
# Leroy 29.07.2013 11:37
похоже великий и могучий ПолтерГейц)))
ev-peregudov
# ev-peregudov 18.08.2013 22:48
Всё круто. Но возникла проблема. Пытаюсь спарсить содержимое

Форматирование теряется, нет перехода на новые строки. Скажите, пожалуйста, как исправить?
ev-peregudov
# ev-peregudov 18.08.2013 22:51
содержимое тега pre
regexp
# regexp 27.08.2013 15:41
пример в начале статьи не корректен:
regexp
# regexp 27.08.2013 15:43
Всю регулярку порезали

'/<a\s+href=”([^”]+)”\s*>(.*?)<\/a>/'
Leroy
# Leroy 27.08.2013 18:40
да? а если юзер добавит вашей ссылке стилей
<div><a style="bla" href="http://xdan.ru"><div>Сайт по программированию парсеров</div><div> и многое другое</div></a></div>


к любому конкретному примеру можно подобрать регулярку, но стоит слегка отойти от это примера и все сломается. simple_html_dom такие перепады не страшны
Максим
# Максим 05.10.2013 05:32
Как правильно работать если страница большая слишком. Мне надо спарсить карту сайта на огромном портале..
Сергей
# Сергей 16.10.2013 21:39
А как парсить много страниц?
Допустим есть сайт site.com
на нем 100 ссылок. И на каждой из тех ссылок еще по 20 ссылок. Получается мне нужно спарсить 2000 страниц в 1 базу. Допустим картинка, описание, телефон.

Второй вопрос: Как парсить только новую информацию на сайте. Например на сайте СМИ обновляются статьи. Я хочу заходить туда раз в сутки(через cron) и забирать только новые статьи в свою базу(а так же если какая то статья из старых обновилась на сайте то ее тоже обновить у себя).

Третий вопрос: Как работать через proxy?

Вообщем хочу для себя создать мощный парсер(с PHP, mysql, HTML работаю давно). Статья лучшая что пока находил по парсерам. НО у меня даже тот пример с Джесикой альбой не получился. Я просто скопировал код и всеравно пустая страница.
Leroy
# Leroy 17.10.2013 17:38
Также и парсить. Циклами и рекурсиями, перебирать все ссылки. грузить их в отдельный объект, также распарсивать и их.

Чтобы знать какие статьи у вас новые, надо запоминать старые. Я обычно если парсил статью, в отдельное поле складывал md5(ее урл) потом сравнивал. Если в базе уже есть такой хеш, то не грузил статью.

Через прокси умеет работать curl
Armen
# Armen 22.10.2013 13:31
добрый день пытаюсь с помощью вашего шаблона сделать парсер для сайта aliexpress.com. но вот на последнем выводе описания почему то не получается вывести

код:

Armen
# Armen 22.10.2013 13:32
<?php
require_once 'simple_html_dom.php';

//url poiska//
$link= file_get_html('http://www.aliexpress.com/store/product/Beats-Audio-Original-phone-HTC-ONE-V-T320e-4G-ROM-WIFI-GPS-5MP-3G-GSM-smartphone/901395_1100253986.html');
$html = str_get_html("$link");

//poisk naxvania tovara <h1> na stranice//
if(count($html->find('h1')))
foreach($html->find('h1') as $title)

//udalyaet vse tegi ostavlyaet tolko tekst//
$w=$title->innertext;

//udalyaet nenujnie slova is teksta//
$endtitle=str_replace(array('shipping', 'smartphone', 'mobile', 'Original', 'free', 'phone', 'GSM', '8MP', '5MP', '3.2MP', '2MP', 'GPS', 'WIFI', 'Wifi', 'ROM', 'RAM', '32G', '16G', '8G', '4G', '3G', '2G', '32g', '16g', '8g', '2g', '3g', '4g', 'new', 'unlocked', 'NEW', 'New', 'brand', 'Brand', 'smartphne','internal','cell', 'big', 'sale', 'In stock', 'HK post', 'Camera', 'camera', 'factory', '100%'), '', $w);

//vivod gotovogo teksta//
echo $endtitle.'(UNLOCKED ORIGINAL NEW)';

//poisk i vivod ceni//
if(count($html->find('span[itemprop=lowPrice]')))
{foreach($html->find('span[itemprop=lowPrice]') as $price)
echo '<br>'.$price;}
else{
foreach($html->find('span[id=sku-price]') as $price)
echo '<br>'.$price;
}

//poisk i vivod ceni//
foreach($html->find('h2[class=description]') as $pr)
echo '<br>'.$pr;


?>
Leroy
# Leroy 22.10.2013 17:38
ну по хорошему все же нужно echo $price->innertext;
Armen
# Armen 22.10.2013 19:39
аа ну да,

а как на счет h2[class=description]?
Leroy
# Leroy 22.10.2013 19:53
а откуда вы вообще взяли этот h2? в странице нет такого тега, как и класса description
Armen
# Armen 22.10.2013 20:30
h2 выводит только Product Description. оттуда начинается описание товара.

"Beats Audio Original phone HTC ONE V T320e 4G ROM WIFI GPS 5MP 3G GSM smartphone free shipping

Product description:



General 2G Network GSM 850 / 900 / 1800 / 1900

3G Network HSDPA 850 / 900 / 2100

SIM Mini-SIM



Announced 2012, February

Status Available. Released 2012, April

Body Dimensions 120.3 x 59.7 x 9.2 mm (4.74 x 2.35 x 0.36 in)

Weight 115 g (4.06 oz)

Display Type Super LCD2 capacitive touchscreen, 16M colors

Size 480 x 800 pixels, 3.7 inches (~252 ppi pixel density)

Multitouch Yes " и т.д.



как вывести именно это описание до картинок? после этого описания выходят картинки.
Leroy
# Leroy 22.10.2013 20:44
понял наконец. не внимательно читали
echo $html->find('h2[class=description]',0)->next_sibling()->innertext
Armen
# Armen 22.10.2013 20:51
спасибо за быстрый ответ, до все равно не отображает. выдает пустоту.(
Armen
# Armen 22.10.2013 21:19
данный код выдает ошибку :

"Fatal error: Call to a member function next_sibling() on a non-object in Z:\home\test1.ru\www\index.php on line 32"

32 линия и есть эта линия что вы написали.
Leroy
# Leroy 22.10.2013 21:27
зачем
$link= file_get_html('...'); 
$html = str_get_html("$link");


когда достаточно
$html= file_get_html('...');


во сторых в html похоже ошибка, и найти он его не может. h2.desc... нет в дом. Парсите этот кусок регуляркой. только не спрашивайте какой.
Armen
# Armen 22.10.2013 19:40
h2[class=description] никак не отображает нужную информацию, а вроде все правильно делаю....
Armen
# Armen 22.10.2013 19:45
вообще то надо вывести описание которое после h2[class=description] идет тоже. т.е. получается div[id=custom-description]
Hrefs
# Hrefs 08.11.2013 00:44
Подскажите, как сделать выборку, если на нужной мне странице стоит тег:

<td class="alt1" colspan="2">


и мне нужно сделать выборку именно по нему, так как нужный текст на странице встречается только после него.

Например я делаю так:

foreach($html->find('td[class="alt1" colspan="2"] ') as $element1) 
echo $element1;


Но ничего не выводится

А если делать так:

foreach($html->find('td[class="alt1"] ') as $element1) 
echo $element1;


то выводится ненужный мне текст, так как тег
<td class="alt1">
встречается на странице несколько раз.

Вариант с указанием позиции тега так:

foreach($html->find('td[class="alt1"] ', 2) as $element1) 
echo $element1;


тоже не подходит, так как нужный текс может встречаться на страницах под разной позицией.
Hrefs
# Hrefs 08.11.2013 00:52
Предыдущий пост коряво отобразился

Подскажите, как сделать выборку, если на нужной мне странице стоит тег:



и мне нужно сделать выборку именно по нему, так как нужный текст на странице встречается только после него.

Например я делаю так:

foreach($html->find('td[class="alt1" colspan="2"] ') as $element1)

echo $element1;

Но ничего не выводится

А если делать так:

foreach($html->find('td[class="alt1"] ') as $element1)

echo $element1;

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

Вариант с указанием позиции тега так:

foreach($html->find('td[class="alt1"] ', 2) as $element1)

echo $element1;

тоже не подходит, так как нужный текст может встречаться на страницах под разной позицией.
Leroy
# Leroy 08.11.2013 02:18
foreach($html->find('td[class="alt1"] ') as $element1)
if( $element1->colspan="2" ){
echo $element1;
break;
}
Hrefs
# Hrefs 08.11.2013 05:15
Спасибо, но все равно отображается не то что нужно.

Вот пример html кода http://i-css.ru.s3.hhos.ru/example.txt

Там только один раз встречается тэг
<td class="alt1" colspan="2">


И нужно спарсить сразу то что следует за ним:
<span class="smallfont"><a href="member.php?u=37470">RixerBox</a>, <a href="member.php?u=32875">Bloomer</a></span>


Но ничего не выходит :(
Hrefs
# Hrefs 09.11.2013 19:30
UPD: уже нашел решение, регулярным выражением оказалось проче чем с использованием Simple-HTML-DOM
barbarisa
# barbarisa 31.12.2013 00:56
На редкость качественный материал. Спасибо!
Замонбек
# Замонбек 08.01.2014 03:48
добрый вечер друзя !

Я хочу парсит сайт ism.uz но столькнуля проблемой не ругайтес ёще я новичок в этом деле ))

Например я хочу парсит страницу http://ism.uz/letter/f/ ну там много ссылок,как парсит эти ссылки? ато не хочу войти каждуйу ссылку и парсит ))
DarkBioloG
# DarkBioloG 14.02.2014 16:55
А как можно спарсить параметр "herf" из тега "a" чтобы он был в формате URL?
Арсен
# Арсен 04.03.2014 23:29
А как парсить пагинацию, например есть лишка с классом "current", нужно достать следующею лишку. Спасибо.
Навка
# Навка 16.03.2014 05:06
Да продлятся твои дни, добрый человек! И только здесь я нашла как именно подключать эту библиотеку! Везде пишут -подключите... Спасибо еще раз!!!
Навка
# Навка 16.03.2014 05:43
Спасибо!! только здесь нашла, как именно нужно подключать это либу! Нигде не могла найти)) И весь урок супер, спасибо!!!
Navka
# Navka 30.03.2014 06:18
Спасибо за статью))) очень полезно и просто. Остался один вопрос. Вы пишите: "Думаю никому в здравом уме, не придет в голову парсить Яндекс с помощью file_get_content." Поэтому собственно и вопрос: а чем надо парсить поисковики? И почему file_get_content не катит?
Leroy
# Leroy 30.03.2014 15:36
поисковики, как и многие умные сайты предпочитают работать не с ботами а с живыми людьми. поэтому проверяется все: наличие кукиес, реферал, операционка, версия браузера, разрешение экрана, некоторые даже анализируют поведение пользователя на странице. Для одного, особо умного сайта, мне пришлось изображать с помощью js на сайте некую деятельность. Прокрутку экрана. По ссылкам парсер не просто переходил а кликал на них.

Большинство сайтов можно спарсить с помощью curl однако в более сложных случая приходится эмулировать браузер (IE COM PHP) или других хитрых методов
Denis
# Denis 04.04.2014 14:36
Здравствуйте. Прежде всего хочу сказать огромное спасибо за очень полезную и качестаенную статью.

Я новичек в php и вообще в программировании в целом, меня всегда интересовал этот вид ТВОРЧЕСТВА и сейчас мне необходимо сделать парсер который удовлетворял бы моим требованиям и спомощью данной статьи я боюсь что это у меня получится.

Собственно вопрос заключается в следующем.

мне необходим парсер каторый мог бы забирать
<iframe>
теги из
id="mediaEmdebCodeInput"
например с xvideos[dot]соm с помощью метода find. Хотелось бы узнать правельный ли у меня ход мысли или это лучше реализовать с посощью других методов. Еще раз Большое спасибо за статью и заранее благодарю Вас за ответ.
Сергей
# Сергей 06.05.2014 09:36
Здравствуйте, добрый Человек!

Я новичок, поэтому не серчайте, пожалуйста! :)



Не могли бы Вы подсказать, как получить данные в следующем примере:



Есть таблица:

<table width=820 cellspacing=1 cellpadding=3 border=0>


<tr bgcolor="#C0C0C0" align=right>
<td>Проход</td>
<td>Прибыль</td>
<td>Всего сделок</td>
<td>Прибыльность</td>
<td>Матожидание</td>
<td>Просадка $</td>
<td>Просадка %</td>
</tr>

<tr align=right>
<td title="данные 1">номер строки 1</td>
<td class=mspt>Прибыль строки 1</td>
<td>Всего сделок строки 1</td>
<td class=mspt>Прибыльность строки 1</td>
<td class=mspt>Матожидание строки 1</td>
<td class=mspt>Просадка $ строки 1</td>
<td class=mspt>Просадка % строки 1</td>
</tr>


<tr align=right>
<td title="данные 2">номер строки 2</td>
<td class=mspt>Прибыль строки 2</td>
<td>Всего сделок строки 2</td>
<td class=mspt>Прибыльность строки 2</td>
<td class=mspt>Матожидание строки 2</td>
<td class=mspt>Просадка $ строки 2</td>
<td class=mspt>Просадка % строки 2</td>
</tr>

</table>



Есть код, которые не работает к сожалению, а по идее должен был бы работать, но, видимо, я ошибаюсь в чем-то, а в чем понять пока не могу:


include("simple_html_dom.php");
$file = 'OptimizationReport.html'; //тут находится таблица

$html = str_get_html($file);


foreach($html->find('tr') as $k => $tr)
{
foreach ($tr->find('td') as $kk => $td)
{
$array[$k][$kk] = $td->plaintext;
}
}




в массив ничего не заносится к сожалению.

Не могли бы подсказать, что не так делаю?



Благодарю!
Сергей
# Сергей 06.05.2014 09:37
Ой, прошу прощения, 2 раза отправилось...
Leroy
# Leroy 06.05.2014 12:06
­str_get_html($file); // берет данные из строки.

Вам нужна file_get_html как минимум
Maxim
# Maxim 18.05.2014 15:56
А что делать, если атрибут class содержит пробелы??
Leroy
# Leroy 19.05.2014 11:11
вопрос уже поднимался. find('class="class1 class2"')
HiPutler
# HiPutler 02.06.2014 18:59
Насколько подобный метод парсинга нагружает сервер-донора, учитывая то что парсится множество страниц в цикле? Обязательно ли прибегать в таком случае к мультипотокам и прокси?
Leroy
# Leroy 02.06.2014 22:41
можно поставить паузу между парсингом
sleep(3)//задержка на 3 секунды
мультипоточный парсинг описан здесь прокси использовать по необходимости, если сервер жестко режет все по ip, в большинстве серьезных кантор это не так. банят по умному, эвристически
HiPutler
# HiPutler 03.06.2014 08:25
Вот спасибо большое добрый программист. И за статью и за совет.
DemonIa
# DemonIa 16.07.2014 18:14
Всем привет. Подскажите, почему вот такой код:
foreach($html->find('a[href*=http]') as $link)
echo $link.'
';
возвращает объект? Я же нигде не указывал индексы, т.е должен быть массив. Мне нужно результат работы парсера записать в csv файл, а функция fputcsv, что очевидно, не может принимать объект. Как быть? Спасибо
Boarworm
# Boarworm 26.07.2014 17:32
Добрый день, решил сделать бота для сайта накрутки лайко, подписчиков и т.д. Авторизацию проходит нормально, заходит на нужную страницу. Далее нужно перейти по ссылке на которой нужно ставить лайк, ссылка вида http://vk.com/............. Я так понимаю нужно спарсить ссылки такого вида, а потом переходить по ним. Пробую так:
$data  = ­file_get_html('http://site.com/user/likes/');
но парсится страница http://site.com/ Может нужно куки как-то передавать?
Dmitriy
# Dmitriy 03.08.2014 01:28
Здравствуйте! А подскажите, как парсить сайт, требующий регистрацию? У меня есть логин пароль, но парсер то зайти через них не может, как быть?
Leroy
# Leroy 03.08.2014 20:30
http://xdan.ru/avtorizacija-na-sajte-pri-pomoshhi-curl-php.html
Валера
# Валера 29.08.2014 19:30
а как строить большой массив? я например хочу взять все ссылки из меню как главные категории и сохранить? затем к этому массиву добавить элементы?

я пробую

$rated = array();

$main_cats = $html->find('.big_menu a');

$rated['main_cats'] = $main_cats;

print_r($rated);

у меня какая-то жесть выводится а не мой массив
Leroy
# Leroy 29.08.2014 21:20
$rated['main_cats'] = array();
foreach($­data->find('.big_menu a') as $a)
$rated['main_cats'][] = $a->href;
Валера
# Валера 29.08.2014 20:04
и еще, пытаюсь добраться до всех li

http://imagizer.imageshack.com/img538/5411/R6gpci.png



foreach($data->find('div.top_menu div.inner ul') as $ul)

{

foreach($ul->find('li') as $li)

{

echo $li;

}

}



но ничего не находит
Leroy
# Leroy 29.08.2014 21:21
в указанном коде все верно, ищите ошибку выше
Andrew
# Andrew 03.09.2014 14:44
Добрый день!

Спасибо за ваш сайт, нашел много полезного.



В парсинг окунулся пару дней назад, знаний мало.

Я спарсил таблицу:

require('simple_html_dom.php');
$html = file_get_html('http://test.com/');
$table = $html->find('table', 0);
$rowData = array();

foreach($table->find('tr') as $row) {
$flight = array();
foreach($row->find('td') as $cell) {
$flight[] = $cell->innertext;
}
foreach($row->find('th') as $cell) {
$flight[] = $cell->innertext;
}
$rowData[] = $flight;
}

echo '<table>';
foreach ($rowData as $row => $tr) {
echo '<tr>';
foreach ($tr as $td)
echo '<td>' . $td .'</td>';
echo '<td>' . $th .'</td>';
echo '</tr>';
}
echo '</table>';



В таблице присутствуют ссылки. От них мне нужно избавится.

Когда ставлю вместо innertext - plaintext, то ссылки уходят, но так же уходят и картинки, которые присутствуют в таблице, поэтому такой вариант не подходит.



Прошу помощи, заранее спасибо.
Фототехник
# Фототехник 09.09.2014 03:36
Можно просто убрать ссылки через css
Andrew
# Andrew 15.09.2014 21:57
Как?

Подскажите, пожалуйста!
Leroy
# Leroy 16.09.2014 19:15
Это он глупость сказал, в ветке ниже есть пример удаления тега h2, замените на a и будет вам счастье
Фототехник
# Фототехник 19.09.2014 00:55
Ну почему же, просто не так выразился*, ссылку можно скрыть с помощью css, Часто так делают на бесплатном хостинге который принудительно вставляет ссылку рекламы.
Andrew
# Andrew 22.09.2014 14:17
Извиняюсь, но можете написать готовый код?) Буду очень благодарен!)
Leroy
# Leroy 22.09.2014 18:28
foreach($data->find('a') as $a){
$a->outertext = ­'';
}
serg47
# serg47 09.09.2014 02:09
помогите пожалуйста. Есть такой кусок:

<div class="slide-content">
<h2 class="slide-title"><a href="http://myautumn.ru/pesni/ohochinskij-yurij-dozhdlivyj-london.html" title="Permalink to Охочинский Юрий &#8212; Дождливый Лондон" rel="bookmark">Охочинский Юрий &#8212; Дождливый Лондон</a></h2>Вот и в Лондон нагрянула осень! Все укрыл бесконечный туман. Ветер листья куда-то уносит. За душой любовь и обман.</div>

Подскажите как выбрать текст после закрывающего тега</h2>?
Leroy
# Leroy 09.09.2014 13:19
удалить h2, потом дернуть то, что осталось
serg47
# serg47 10.09.2014 02:17
Спасибо за ответ!


include 'simple_html_dom.php';
$data = file_get_html('http://yyyyyyu.ru');
foreach($data->find('.slide-content') as $main){
$b=$main->find('h2');
$b->outertext = '';
echo "$main->plaintext";
}


Пытаюсь так, но не получается. Пните в нужном направлении! Заранее спасибо!
serg47
# serg47 10.09.2014 16:14
Если кому интересно "докумекал" рабочий вариант :


include 'simple_html_dom.php';
$data = file_get_html('http://myautumn.ru');
foreach($data->find('.slide-content') as $main){
$b=$main->find('h2',0);
$b->outertext = '';
echo $main->innertext.'<br /><br />';
RomHunter
# RomHunter 17.09.2014 13:47
Отличная статья, спасибо!
blackx1
# blackx1 19.09.2014 00:58
Спасибо, хорошая статья

Только вот интересно когда такой случай

Когда есть к примеру " <b>Название: </b>Название1<br />"

Как вытянуть "Название1"?
Leroy
# Leroy 19.09.2014 11:37
К сожалению никак, через библиотеку этого не сделать. Нужно как-то брать корневой для этих тегов элемент и уже анализировать его содержимое через регулярные выражения. Вообще, для парсинга хоть я и написал, что регулярки не очень удобны, но в отдельных случаях они незаменимы.
irirni
# irirni 27.09.2014 23:00
Спасибо за статью!
Oleg
# Oleg 29.09.2014 14:12
Добрый день! Спасибо за библиотеку. Немного разобраться не могу в ней. Требуется из примерно такого хтмл кода дернуть нужный текст и нужные ссылки

<div id="bar"><ul>

<li><a href="/zakon/2014/">не нужная ссылка 2014</a></li>

<li><a href="/">не нужная ссылка</a></li>

<li><a href="/zakon/">не нужная ссылка</a></li>

<li><a href="/catalog/">не нужная ссылка</a></li>

<li><a href="/forum/">не нужная ссылка</a></li>

</ul></div>

<div><a href="/info/423/">нужная ссылка</a></div>

<div>нужный текст</div>

<div>нужный текст</div>

<div style="margin-top: 10px"></div>

<div><a href="/info/472/">нужная ссылка</a></div>

<div>нужный текст</div>

<div>нужный текст</div>

<div style="margin-top: 10px"></div>

<div><a href="/info/732/">нужная ссылка</a></div>

<div>нужный текст</div>

<div>нужный текст</div>

<div style="margin-top: 10px"></div>



в пхп прописываю так:

$data_ooo = file_get_html($arr_city[27]);
if($data_ooo->innertext!='' and count($data_ooo->find('a'))){
foreach($data_ooo->find('a') as $c){
$b = $c->find('li,ul',0);
$b->outertext = '';
//$data_ooo->innertext;
echo '<a href="http://www.vutil.ru'.$c->href.'">'.$c->plaintext.'</a></br>';
//echo $c->innertext;
}
}




но что то не выходит, помогите плиз!
Парсер
# Парсер 04.01.2015 21:47
Прочитайте про DOM и HTML.

Вы сначала получаете список тегов <a>, а потом в них ищете <li> хотя в HTML которые вы привели в качестве примера во всех тегах <a> только текст.



Смысл самого кода написанный вами непонятный.
Сергей Пил
# Сергей Пил 29.11.2014 10:39
Здравствуйте написал вот такой парсер.


<?php
//ставим лимит памяти больше, т.к. библиотека затратна к ресурсам
ini_set('memory_limit', '128M');
//так же ставим больше время сессии
set_time_limit(800);
//начинаем сессию
session_start();
require_once 'simple_html_dom.php';
$data = new simple_html_dom();
$data = file_get_html('http://www.mon.gov.ua/ua/news');
if($data->innertext!='' and count($data->find('aside#leftSideBar'))){
?>
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Тег А, атрибут target</title>
</head>
<body><?
foreach($data->find('div.standartBlock') as $aside){
$aside = preg_replace("/[\n\r\t]/", '', $aside); // замена символов перевода строки и табул¤ции на пробел
$aside = preg_replace("/[ ]{2,}/", '', $aside); // замена более 2х пробелов на один

$div ='<div class="data">';// готовим для даты подмену шаг 1
$div1 ="</div>";// готовим для даты подмену шаг 2
$today = $div. date("d.m.y"). $div1;// готовим для даты подменушаг 3
$aside = preg_replace('/\<span class\="date"\>(.+)\<\/span\>/is', $today, $aside);// замена класса даты на текушюю
$aside = preg_replace('/\<div class\="standartBlock stBlockBlue\">(.+)\<\/div\>/is', '', $aside);
$aside = preg_replace('/\<div class\="image\">(.+)\<\/div\>/U', '', $aside);
$aside = str_replace('<span>', '', $aside);
$aside = str_replace('</span>', '', $aside);
$domain = "http://www.mon.gov.ua";
$new = preg_replace('#(<a href=")(.*)(">)#', "$1$domain$2$3", $aside);


echo $new;
}
}
//освобождаем ресурсы
$data->clear();
unset($data);
?>

Всё в роди нормально, но хочу чтобы можно было указывать определённое количество новостей, кто знает подскажите пожалуйста.
Елена
# Елена 11.12.2014 15:48
Не пойму что делаю не так.


ini_set('display_errors', 1);
ini_set('mbstring.func_overload', 0);

// example of how to use basic selector to retrieve HTML contents
include($_SERVER['DOCUMENT_ROOT'].'/simple_html_dom.php');


// get DOM from URL or file
$html = file_get_html('http://yandex.com/images/search?text=%22odeonlight%22+2553%2F7+ODL13+004+%D0%B1%D1%80%D0%BE%D0%BD%D0%B7%D0%B0+%D0%9B%D1%8E%D1%81%D1%82%D1%80%D0%B0++E14+7*40W+Rika&itype=&nojs=1&rpt=image&tld=com');


/*echo '<pre>';
print_r($html);
echo '</pre>';*/

$ret = $html->find('img');
echo '<pre>';
print_r($ret);
echo '</pre>';

В переменной $ret ноль. Я ставила другие теги. Так же всё по нулям. Точнее ищет только html тег
Парсер
# Парсер 04.01.2015 21:39
Вы сами перейдите по той ссылке что указали в


$html = ­file_get_html('http://yandex.com/images/search?text=%22odeonlight%22+2­553%2F7+ODL13+004+%D0%B1%D1%80%D0%BE%D0%BD%D0%B7%D0%B0+%D0%9B%D1%8E%D1­%81%D1%82%D1%80%D0%B0++E14+7*40W+Rika&itype=&nojs=1&rpt=im­age&tld=com');

Вообще блок с картинками отдается AJAX запрсом, поэтому тут таким простым подходом не ограничишься.
Парсер
# Парсер 04.01.2015 21:37
В своем коде я так же чищу и полученные элементы, к примеру


$a->clear();

потому что из-за них память тоже засоряется
VASILIYYY
# VASILIYYY 26.02.2015 01:23
Отличная статья! Скажите, а если при получении html страницы она очень велика - несколько миллионов символов, библиотека просто отказывается ее обрабатывать, какие есть варианты решения проблемы? При этом если получать страницу курлом и сразу кидать ее на вывод, она выводится, так что дело именно в simple html dom. Спасибо.
Leroy
# Leroy 26.02.2015 07:44
как вариант выдирать регуляркой нужный кусок текста и уже его скармливать библиотеке.
Валерий
# Валерий 26.02.2015 05:44
Полезная статья! А не подскажите, можно ли из элемента код распарсить код, либо получить значение конкретной переменной этого скрипта (основная цель этого упражнения)?
К примеру, на загружаемой странице есть скрипт ниже:

var flashvars = {
uid: 'videoplayer',
file: 'http://',
poster: 'http://...jpg',}
var params = {
bgcolor: '#000', ...}

$html = file_get_html('http://пример.php'); //Загружаю страницу
foreach($html->find('script') as $element) //парсю все скрипты
echo $element->plaintext . ''; //а дальше не знаю как вывести код скрипта, либо вывести значение переменной flashvars:file
Можно ли такое проделать с этим парсером?
Валерий
# Валерий 26.02.2015 05:47
*речь об элементе < s c r i p t > код < / s c r i p t >
Leroy
# Leroy 26.02.2015 07:47
нет. содержание элемента это не задача этой библиотеки. Содержание нужно распарсивать уже регулярным выражением, т..е. в вашем случае примерно так
if(preg_match('#file:'(.*)',#Uus', $element->plaintext, $list)) {
echo $list[1];
}
Валерий
# Валерий 26.02.2015 08:01
Спасибо за ответ! Да, похоже только регулярными выражениями можно распарсить содержание скрипта и выдернуть значение переменной.
cookie
# cookie 11.03.2015 20:41
Я не понял как соединять результаты ответов, в плане, что я хочу одним скритом найти ссылку, а уже потом парсить информацию по этой ссылке. Мне выкидывает ошибку. Что делать?
Andrey
# Andrey 14.03.2015 03:56
Спасибо Вам огромное!

У меня вопрос:

Можно ли в выборке попросить чтобы название класса начинолось на x и кончалось на y?

Что-то вроде этого:

div[class^=x && $=y]
campusboy
# campusboy 14.03.2015 08:52
Я новичкок, возможно, глубоко не смог разобраться, но эта библиотека не дала мне решения в задаче. Были на сайте блоки DIV, у которых был класс типа text_523547. Мне нужно было не только парсить текст внутри блоков, но и сохранять в базу вот это число именно. Библиотекой не смог, сделал на регулярках. И ещё не понравилось. К примеру, на странице есть одна ссылка, я нахожу её библиотекой и помещаю в переменную. Потом через var_dump хочу посмотреть, что внутри. В общем, 4ГБ моей ОЗУ оказалось недостаточным, чтобы просмотреть на экране через ХРОМ, что же есть внутри. Там куча хлама. А для новичка важно наглядно видеть, что внутри переменной, чтобы потом оперировать с данными. В итоге, регуляркой решил вопрос (и удобно смотреть что внутри переменных), плюс она работает в среднем 0,5 секунды, когда библиотека в среднем 0,7-1сек.
Дмитрий Николаев
# Дмитрий Николаев 22.04.2015 15:42
Добрый день,очень буду благодарен если толкнете в правильном направлении реализации задуманного.
Есть сайт с авторизацией,авторизированому пользователю доступен контент на определенной странице этого сайта,часть этого контента автоматически обновляется 1 раз в час,необходимо разместить часть этого контента на странице другого сайта с теми же функциями автоматического обнавления.

Хожу вокруг да около,вроде рядом,но не могу понять как реализовать.
Leroy
# Leroy 23.04.2015 09:44
Вот тут http://xdan.ru/avtorizacija-na-sajte-pri-pomoshhi-curl-php.html почитайте. То что вам нужно
Andrey
# Andrey 14.08.2015 03:25
Добрый день, а можно ли запарсить атрибут style?

Пробовал так:


$bgPos = $digit->getAttribute('style');
echo $bgPos. '';


И так:
echo $digit->style . '';


Почему то не вышло(
Leroy
# Leroy 14.08.2015 11:30
и первый и второй вариант верны, ищите ошибку где-то выше
Владимир М
# Владимир М 24.08.2015 10:23
Есть ресурс http://rabota.e1.ru/vacancy?rubric[]=50 который при парсинге вакансий ничего не отдает, хотя http://rabota.e1.ru выдает все номально.
Код:


При обработке выдает ошибку:
Fatal error: Call to a member function find() on a non-object in C:\OpenServer\domains\localhost\index.php on line 5

Как я понимаю в следствии пустого обьекта.
Прошу помочь составить запрос.
kuller
# kuller 24.09.2015 21:24
Не могу чета понят. Помогите разобраться. Допустим код из примера который парсит картинки выводит их на страницу, а если надо каждой картинке спарсит еще описание, как это сделать? Что только и не пробовал сделать. Сейчас вот такой вид

foreach($data->find('h2.zagolovki') as $txt)
{
$htmls = $txt->innertext;

$a++;
if($a>$n)break;
}

foreach($data->find('div.shortimg a img') as $img)
{
$arr = explode("/", $img->src);

echo $htmls.'';

$i++;
file_put_contents('uploads/'.($arr[5]).'.jpg', file_get_contents($img->src));
if($i>$n)break;
}

результат работы, для каждой картинки берется одинаковый заголовок. Что не так?
Виктор Назаров
# Виктор Назаров 30.10.2015 20:02
Подскажите, а как заменить ссылку, оставив текст
например Игры онлайн как заменить http://igroflot.ru/ на http://site.ru?
К сожалению php не знаю, а в комментариях похожего случая не было.
Виктор Назаров
# Виктор Назаров 30.10.2015 20:28
К сожалению html не отобразилось, вот пример:
  • Игры онлайн как заменить http://igroflot.ru/ на site.ru?
Виктор Назаров
# Виктор Назаров 30.10.2015 20:30
a href = "igroflotru/" >Игры онлайн
Leroy
# Leroy 03.11.2015 14:15
http://php.net/manual/ru/function.str-replace.php
Vladimir
# Vladimir 22.12.2015 15:10
Помогите спарсить отсюда http://101.ru/?an=personal_playlist&userid=489993

Самое верхнее название исполнителя и трэка, вот часть из кода:

Цитата:



KEIFER, Tom - Blue Christmas
Отсюда нужно забрать "KEIFER, Tom - Blue Christmas"

Спасибо!
Vladimir
# Vladimir 22.12.2015 15:12
Код некорректно отобразился:




KEIFER, Tom - Blue Christmas


из этого нужно забрать "KEIFER, Tom - Blue Christmas"
АлександрАнатольевич
# АлександрАнатольевич 29.01.2016 23:15
Спасибо огромное! Очень помогло)
Было бы интересно увидеть настолько же подробный мануал по парсингу сайтов с защитой.
Может быть есть готовые библиотеки с эмуляцией браузера? Наподобие зеннопостера только на PHP
Александрqazzzqsa
# Александрqazzzqsa 31.01.2016 21:56
Как найти элемент по тексту между тегами? Например Employment type
Пробовал
$html->find([text()='Employment type'])
$html->find('Employment type')
не получается(
jkeksa
# jkeksa 31.03.2016 08:08
Спасибо, но все же регулярками иногда прощще найти что-то..
Часто надо выдернуть какой-то контент из текста, хотя по ДОМу лазиить лучше конечно селекторами.
С другой стороны.. оба этих метода легко крошатся при модификациях страниц.
Leroy
# Leroy 01.04.2016 09:10
ну лазить по дому все же надежнее и при модификации страницы селекторы поправить проще. Можно их в конфиге парсера к примеру все держать. С регулярками так тоже можно, но так вот просто не поправишь, надо тестить, смотреть окружение. Проверить под все ли случаи подходит.
А так да, я совмещаю и регулярки и дом. Если нужно выдернуть одно единственное значение то конечно лучше регулярки
Евгений
# Евгений 19.07.2016 17:25
никто не подскажет в чем ошибка ? переменная $zz нече не парсит
Код: foreach($html->find('#allEntries') as $a){
$jj = $a->plaintext;
$zz = $a->find('.vnewtop')->plaintext;
Ivan26ru
# Ivan26ru 09.08.2016 01:03
Цитирую Евгений:
никто не подскажет в чем ошибка ? переменная $zz нече не парсит
Код: foreach($html->find('#allEntries') as $a){
$jj = $a->plaintext;
$zz = $a->find('.vnewtop')->plaintext;


find('.vnewtop') ищет все элементы с классом vnewtop, и добавляет в массив, а plaintext выводит чистый текст уже для конкретного элемента.
Решение:
$zz = $a->find('.vnewtop');
foreach($zz as $zzz){
echo "Тест zzz: " . $zzz->plaintext;
}

примерно так, но могу и ошибаться)
Александр8839
# Александр8839 22.08.2016 23:13
$img = $data->find('img', 0);
$img_src = $img->src;
echo $img_src->outertext;
Почему не работает? Пишет: Trying to get property of non-object in
Хочу заменить урл в src на свой, как это сделать?
Leroy
# Leroy 23.08.2016 07:21
$img_src это просто текст, зачем вы к нему образщаетесь $img_src->outertext
K. K.
# K. K. 02.09.2016 02:33
deleted
K. K.
# K. K. 02.09.2016 02:37
deleted
campusboy
# campusboy 02.09.2016 02:51
Долго - это сколько?
Андрей64646464646464
# Андрей64646464646464 18.09.2016 09:10
Явно автор забыл про новичков... Ну да, зачем вообще что то обьяснять, когда можно показать на сколько ты крутой и все и так понимаешь... Что, откуда и куда не понятно. Даже тратить время не буду. Задрали со своими гавносайтами! Учитесь обьяснять и разжовывать!
Leroy
# Leroy 20.09.2016 09:21
)))) а вы наверно денег хотите заплатить за разжевывание?)) А то как-то непонятно, автор потратил время, написал статью, а вы даже спасибо не удосужились написать.
campusboy
# campusboy 04.10.2016 16:22
Ну хоть время для выливания говна у тебя хватает. Жаль вот время на разбор примеров его нет.
Drop
# Drop 04.10.2016 16:18
Сделал такой парсер.
$link = $_POST['page'];

include('simplehtmldom/simple_html_dom.php');
$html = file_get_html('http://weplay.tv/csgo/tournaments');
$rated = array();

foreach($html->find('td') as $t1)
echo $t1->plaintext;
#print_r($rated);
$html->clear();
unset($html);
хочу спарсить таблицу. Но класс есть только у первого и последнего столбца. Как сделать так, чтобы парсились только те строки, у которых в 5 стобце класс status complete ?
Женя
# Женя 10.11.2016 19:24
Всем привет , поделитесь опытом как можно при помощи этой библиотеки пропарсить все страницы сайта пример или пошагово ? то есть насколько я понимаю начинаем искать ссылки на страницах и переходим по этим ссылкам но не совсем понятно как избавится от дублей и ссылок на другие сайты
Max
# Max 01.06.2017 11:29
Составляешь массив ссылок, при добавлении новой записи проверяешь есть запись ссылка или нет. Ссылки на другие сайты опять же проверкой строки, отризаешь через php название сайта и проверяешь тот сайт или нет. Другое дело непонятно когда нужно остановить процесс сканирования, таймер какой ни будь поставь что бы не зависло)
Max
# Max 24.05.2017 13:10
Помогите пожалуйста разобраться в вопросе возможностей curl.
Есть сайт http://game-tournaments.com/dota-2/prodota-cup-sea-8 Заходя на сайт через curl он видит уже нарисованную страницу, на сайте можно переключать букмекера представляющего коэффициенты тогда идет POST запрос на ajax и потом в php обрабатывается запрос и отрисовываются новые коэффициенты без перезагрузки страницы. К сожалению curl видит только начальную страницу, возможно ли как то сделать так что бы curl заходил на страницу менял переключатель и только потом забирал страницу? пробовал генерировать curl с POST запросом без успешно, видимо форма его не отлавливает там. Подскажите направление к решению если оно конечно есть.
igorroi
# igorroi 09.06.2017 13:50
Добрый день!
Написал мини-парсер по данной статье, но очень много времени занимает обработка одной ссылки (3-4 секунды). Это нормально или я что-то делаю не так?
Олежка
# Олежка 29.06.2017 08:03
Здравствуйте. Подскажите как спарсить структуру которая открывается по клику ?
Max
# Max 06.07.2017 08:07
Надо смотреть сайт, что именно срабатывает при нажатии, либо там POST, GET запрос идет на сервер и сервер отрисовывает вам данные после клика, или JS скриптом просто спрятано что то.
vlad
# vlad 08.08.2017 11:26
если я делаю $data->find('text') то как мне исключить тексты в h1 и title из этой выборки?
Max
# Max 08.08.2017 17:57
Если там возвращается только текст без тега в коде то ни как. Самый простой вариант пробежаться по всему дереву и убадить весь текст с тегом h и title, что то типо $newdata=$data->find('h')->outertext='' Делать это через цикл. Еще можно помучится с проверкой тега у див элемента, не знаю работает такое или нет, типо h1['class'!=title], надо смотреть искать за что зацепиться.
vlad
# vlad 09.08.2017 16:57
как делая find('text') исключить текст тегах script и style?
vlad
# vlad 16.08.2017 08:59
делаю
для https://zanimayonlayn.ru/mikrokredity/chestnoe-slovo.php
$data = file_get_html($url);
результат при попытке искать в $data Call to a member function find()
не создало объект
почему?

кривой html код ?
Max
# Max 16.08.2017 09:20
html не может получить данные с файла php, делайте file_get_contents
serg
# serg 28.08.2017 01:59
Подскажите как сделать задержку парсинга? не знаю как правильно объяснить.... делаю парсер объявлений и как я понимаю если выполнить скрипт парсинга, тогда пойдет сразу сохранение всех объявлений.... а как сделать чтоб сохранения были поочередно т.е. сохраняем одно объявление, после идет задержка например 30 сек. и потом сохранение второго объявления и так далее. Если я просто пропишу sleep будет ли тот результат который требуется или это надо как та уже в связке js писать?
Max
# Max 28.08.2017 10:12
Не совсем понятно что вам нужно. Если сохранение данных в вашу бд, то можно сделать как угодно, если же вы хотите каждое объявление вытаскивать с сайта через 30 секунд тогда нужно в цикле делать новый конект к сайту и искать следующее объявление. За один конект curl вытащит весь сайт и контролировать по скорости как он должен парсить сайт вы не сможете. Только делая новый конект допустим через тот же sleep. Не понятно зачем вам это на самом деле.
serg
# serg 28.08.2017 16:51
если вытаскивать сразу все объявления с сайта идет соотвествено большая нагрузка. Так же может выдать ошибку и за не хватки времени выполнения скрипта. В других парсерах на сколько я помню чтоб этого не происходило делают небольшую задержку после каждого сохраненного объявления.
Max
# Max 29.08.2017 10:24
С чего вы взяли что идет нагрузка на сайт с которого вы берете данные? Там ровно такая же нагрузка как если бы вы зашли на эту страницу с браузера (по сути curl эмитируется ваш браузер, забирает dom дерево), другое дело если вы сразу вытаскиваете кучу страниц, или делаете какие ни будь редиректы с одной страницы на другие страницы где находятся другие объявления, тогда в коде уже можно написать функцию задержки при редиректе. Если же страница одна, тогда нагрузка у вас идет при сохранении на ваш собственный сервер, работа с DOM деревом может занимать много времени если алгоритм достаточно сложный, но это опять же на совести самого программиста, как написан алгоритм.
Max
# Max 29.08.2017 10:30
Если уж времени не хватает попробуйте функцию CURLOPT_TIMEOUT, у меня есть сайты с которых данные загуржаются более минуты и библиотека отлично с такими объемами справляется. Если не поможет, тогда делайте новый конект в цикле, допустим нужно сделать редирект на страницу с новыми объявлениями, обновляйте конект к новой странице.
ivanov.ivan
# ivanov.ivan 11.12.2017 18:20
Здравствуйте. Большое спасибо за статью. Очень познавательно.
Есть вопрос: есть сайт, просит логин и пароль для входа и только потом дает нужную мне страницу.
Как это автоматизировать разобрался, curl помог, получаю следующую страницу с нужным мне контекстом.
На этой второй странице есть список, при изменении которого меняются данные страницы.
Страницу с этим списком в переменную получаю. Поиском foreach($html->find("select")as $s) успешно этот список нахожу. Но не могу понять как заставить его изменить значение.....
В отладчике chrome все просто:
1) var mlist = $$("select")
2) mlist[0].value='нужное мне значение'
3) mlist[0].onchange()
и я попадаю на нужную мне статистику, но это в консоли chrome, а как сделать пукнт 2 и 3 через php ?
Дми-трий
# Дми-трий 11.06.2019 10:35
Добрый день ! Подскажите такую штуку - кладу папку с этим парсером и всеми его файлами, а как их подключить из другой директории ?

Если я кладу файл "simple_html_dom.php" в корень, то все работает, если кладу его к примеру в common/parser то получаю "пустую страницу" без контента

Т.е. я так понимаю что файлы плагина между собой как то связаны "путями" или как то "завязаны" на корне сайта

Пример boogiwoo.ru - внизу парсятся отзывы с вк
R7KD
# R7KD 30.06.2019 01:08
Прошу помощи. У меня при парсинге с другова сайта идет следующий код
Код:<iframe width="100%" height="350" src="https://www.youtube.com/embed/BnR1MfWbKhM" frameborder="0" allowfullscreen=""></iframe>
Мне надо вырезать из этого кода Код:width="100%" height="350" к записи на сайт.
Можно ли вырезать Код:width="100%" height="350"
Если это возможно, напишите код скрипт с помощью которого я это могу сделать.
Настя999
# Настя999 30.06.2019 01:19
Прошу помощи. У меня при парсинге с другова сайта идет следующий код
Код:<iframe width="100%" height="350" src="https://www.youtube.com/embed/BnR1MfWbKhM" frameborder="0" allowfullscreen=""></iframe>
Мне надо вырезать из этого кода Код:width="100%" height="350" к записи на сайт.
Можно ли вырезать Код:width="100%" height="350"
Если это возможно, напишите код скрипт с помощью которого я это могу сделать.
Александр В.
# Александр В. 13.07.2020 20:00
Неплохо, весьма неплохо