Skip to content

socialink/pageparser

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

11 Commits
 
 
 
 
 
 

Repository files navigation

PageParser 0.2

0.2 (2011.01.02)
	- добавлен новый метод DOMFindAll
	- findAll теперь в любом случае не возвращает $m[0] (Если $m[0] где-то нужен, всегда можно добавить скобки /(...)/)
	- добавлена новая конструкция each()
	- переименованы методы select, rm, rmempty, теперь так:
		rmById(n1,n2,..,ni) - удалить элементы n1,n2,..,ni из $html by id (синонимы: rmBI, removeById, removeBI, deleteById, deleteBI, delBI, remById, remBI)
		selById(n1,n2,..,ni) - оставить только элементы n1,n2,..,ni, остальные удалить (синонимы: selBI, selectById, selectBI)
		rm(regexp) - удалить элементы, которые подходят под regexp (синонимы: del,delete,rem)
		sel(regexp) - оставить только элементы, которые подходят под regexp (синонимы: select)

0.14 (2010.11.24)
	- изменение в методе match. Теперь $m[0] не возвращается в любом случае.

0.13 (2010.11.13)
	- добавлен новый метод select (select element).

0.12 (2010.11.03)
	- добавлен новый метод findAll.
	- добавлен новый метод replace.
	- добавлен новый метод select.

0.11 (2010.11.02)
	- добавлен новый метод rmempty.

0.1 (2010.11.01)
	- первая версия PageParser.




Класс для парсинга кода html-страницы.

Идея:
	пусть имеется html-код страницы, из которого нужно извлечь фиксированные данные. 
	Зачастую, обычный парсер - несколько хаотичная смесь регулярных сплитов и preg_match-ей (php). 
	Главная цель данного класса - стандартизация процесса парсинга страницы, единообразие команд.
	Вместе с тем, есть несколько оригинальных методов, упрощающих парсинг (например preg_match с учетом dom-структуры).

$pp = new PageParser();

Каждый метод возвращает ссылку на объект, поэтому возможен вызов по цепочке типа
$pp -> setOpt(..) -> set(..) -> split(..) -> findDom(..) -> save(..);

Устройство:
	Объект $pp содержит стек $htmls, каждый элемент стека - одномерный массив из строк.
	Активным элементом стека всегда является последний добавленный элемент (он извлекается функцией array_pop).
	Большинство методов берут активный элемент стека, что-то с ним делают и перезаписывают его значение.

	$this->htmls - стек html-строк.
	$html = array_pop($this->htmls) - через $html в методах обычно обозначается активный элемент стека.  

	set($html)
		- добавляет в стек $htmls новый элемент $html.
		- если $html - строка, в стек добавляется array(0=>$html).
		- если $html - массив, в стек добавляется массив из его значений (array_values). Ключи элементов массива намерено теряются.

	save(&$var)
		- записывает в переменную $var значение активного элемента стека ($html).
		- если $html - массив с одним элементом, возвращается значение элемента, в другом случае - весь $html.

	save(&$var,function)
		- перед записью к значению применяет func.

	begin(),b()
		- дублирует активный элемент стека (делает копию активного элемента и кладет ее в стек).
	
	end(),e()
		- удаляет из стека последний элемент.

	find(param1,param2)
		- выбирает строку, заключенную между param1 и param2 и перезаписывает получившимся значением активный элемент стека.
	find(param1,...,paramN)
		- выбирает все что после param1. Из получившегося - выбирает все что после param2, итд. до последнего элемента. 
		- последняя итерация - выбирает все что ДО paramN.
	find(param1,...,"*",...,paramN)
		- выбирает все что после param1, итд до элемента - '*', а после '*' выбирает все что до paramI+1,..,paramN.
	find(param1)
		- вызывает функцию preg_match(param1,$html,$m); Если $m - массив из двух элементов (т.е. в регулярном выражении - одни скобки), берет $m[1], в другом случае - весь массив $m без $m[0].

	DOMfind(tag_start,tag_end,obstacle)
		- задача - выбрать все между tag_start и tag_end c учетом препятствия obstacle.
		- пример 
			- нужно выбрать блок в <div>-ах, при этом в этом блоке так же могут быть внутренние блоки из "<div>...</div>", и это нужно учесть.
			- рассмотрим
				<div class=a>
					...
					<div>...</div>
					<div>...</div>
				</div>
			- нужно выбрать содержание дива class='a'.
			- Пишем: ->DOMfind("/<div class=a>/","/<\/div>/","/<div>/")
			- это выражение выберет подстроку за tag_start, 
			- затем будет искать tag_end, но каждое встреченное до него препятствие obstacle увеличит внутренний счетчик. 
			- каждый встреченный tag_end уменьшает счетчик. 
			- процесс идет пока счетчик не обнулится.

	findAll(param1,...,paramN)
		- фактически обертка для preg_match_all. То же самое, что find, только ищет все вхождения, и все вхождения складывает в стек.

	split(p)
		- разбивает $html по выражению p на массив строк.
		- если активный элемент стека - уже массив из строк, разбивает каждый элемент массива на строки и складывает все получившиеся строки в один массив. 
		- в любом случае результат всегда одномерный массив из строк.

	split(p,limit,num)
		- разбивает $html по выражению p на массив строк с limit - количество кусков. num-ный кусок сохраняет в стек.
		- если $html - массив из нескольких элементов, разбивает по p каждый элемент с лимитом limit и выбирает num-ный кусок из каждого элемента.

	rmBI(n1,n2,...,ni) (removeById)
		- удаляет n1,n2...ni - е элементы массива $html, при этом меняется количество элементов в стеке-массиве.

	selBI(n1,n2,...,ni)
		- оставляет только n1,n2,...,ni - е элементы массива $html, при этом меняется количество элементов в стеке-массиве.

	rm(param1,...,paramN)
		- удаляет те элементы массива $html, которые подходят хотя бы под один регексп из param1,...,paramN.

	sel($param1,$param2,...,$paramN)
		- оставляет только те элементы массива $html, которые подходят хотя бы под один регексп из param1,...,paramN.

	replace($s1,$s2)
		- обертка для preg_replace($s1,$s2,$html), применяется ко всем элементам массива $html.
	

	Большой пример:
	Есть данные в таблице:
		<table id="data">
			<tr>
				<td><table><tr><td><img src="/im/object1.gif"></td></tr></table></td>
				<td><a href="/?id=1">Object 1</a></td>
				<td>$100</td>
				<td>2011.01.01</td>
			</tr>
			<tr>
				<td><table><tr><td><img src="/im/object2.gif"></td></tr></table></td>
				<td><a href="/?id=2">Object 2</a></td>
				<td>$200</td>
				<td>2011.01.01</td>
	</tr>
			<tr>
				<td colspan=2><a href="/?id=3">Object 3</a></td>
				<td>$300</td>
				<td>2011.01.01</td>
			</tr>
		</table>
	Нужно написать парсер, который из данного кода получит массив:
	$data = array(
		0 => array("id"=>"1","name"=>"Object 1","price"=>"100","date"=>"2011.01.01","img"=>"/im/object1.gif"),
		1 => array("id"=>"2","name"=>"Object 2","price"=>"200","date"=>"2011.01.01","img"=>"/im/object2.gif"),
		2 => array("id"=>"3","name"=>"Object 3","price"=>"300","date"=>"2011.01.01","img"=>""),
	);

	Пусть html-код находится в переменной $str.

	Решение: 

	$pp = new PageParser();
	$pp	-> set($str)
		-> DOMFind("/<table[^<>]*id\s*=\s*[\"']?data[^<>]*>/","/<\/table[^<>]*>/","/<table[^<>]*>/")
		-> DOMFindAll("/<tr[^<>]*>/","/<\/tr[^<>]*>/","/<tr[^<>]*>/")
		-> each()
			-> DOMFindAll("/<td[^<>]*>/","/<\/td[^<>]*>/","/<td[^<>]*>/")
			-> b()
				-> selBI(0)
				-> find("/<img[^<>]*src\s*=\s*[\"']?([^<>\"']*)[\"']?[^<>]*>/")
				-> save($tmp[img])
			-> e()
			-> b()
				-> selBI(1)
				-> b()
					-> find("/\/\?id=(\d+)/")
					-> save($tmp[id])
				-> e()
				-> save($tmp[name],"strip_tags")
			-> e()
			-> b()
				-> selBI(2)
				-> replace("/[^\d\.]/","")
				-> save($tmp[price])
			-> e()
			-> b()
				-> selBI(3)
				-> save($tmp[date])
			-> e()
		-> endEach();

	$data = array();
	foreach($tmp[id] as $i => $ar1)
		$data[] = array("id"=>$tmp[id][$i][0],"name"=>$tmp[name][$i][0],"price"=>$tmp[price][$i][0],"date"=>$tmp[date][$i][0],"img"=>$tmp[img][$i][0]);
		


About

Some classes for parsers (grabbers).

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • PHP 100.0%