Это архивная статья. Блог закрыт.

← на главную

cURL для начинающих. Пишем парсер

Статья написана очень давно — 29.01.2010

Начинающий программист зачастую пугается многих страшных слов, когда ему советуют для определённой задачи использовать что-либо. В этой статье я хочу развеять страх перед таким словом, как cURL

Итак, что же такое cURL? Вообще, cURL - это консольная программа, которая предназначена для передачи файлов по различным протоколам. Само название cURL - это сокращение от "client urls". В PHP же cURL - это подключаемый модуль. Раскомментируйте строчу extension=php_curl.dll в файле php.ini, перезагрузите сервер и модуль подключен! (Имеется ввиду локальный сервер под Виндовс, типа денвера, а на большинстве хостингов этот модуль установлен и включён)

Механизм работы курла примерно таков: Вы подключаетесь по определённному адресу, устанавливаете параметры, получаете контент запрошенной Вами страницы и отключаетесь. Всё просто, а на практике ещё проще. Для начала простой грубый пример, а позже напишем полноценный парсер:

//Инициализация cURL и задание адреса
$ch = curl_init('http://example.com/page2');
//Установка опций
curl_setopt($ch, CURLOPT_USERAGENT, 'KOZ1024 Site Parser');
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_REFERER, 'http://example.com');
//выполнение (результат отобразится на экран)
curl_exec($ch);
//Закрытие соединения
curl_close($ch);

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

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
<title>KOZ1024 Site Parser</title>
<script>
var xmlHttp = false;

function start(){
	//"включаем" картинку загрузки
	document.getElementById('progressbar').innerHTML = '<img src="/images/ajax-loader.gif" border="0" alt="Loading, please wait..." />';
	//инициализация ajax
	try{
		xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
	}catch (e){
		try{
			xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
		}catch (e2) {
			xmlHttp = false;
		}
	}
	if (!xmlHttp && typeof XMLHttpRequest != 'undefined') {
		xmlHttp = new XMLHttpRequest();
	}
	//открываем страницу parser.php
	xmlHttp.open("POST", 'parser.php', true);
	//Устанавливаем заголовок - говорим, что это форма
	xmlHttp.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
	//задаём функцию-обработчик результата
	xmlHttp.onreadystatechange = parseResult;
	//отправляем запрос
	xmlHttp.send('url='+document.getElementById('url').value+'&types='+document.getElementById('types').value+'&max='+document.getElementById('max').value);
}

function parseResult(){
	//функция-обработчик: если состояние = 4 ("полностью загружено"), то вставляем результат работы скрипта вместо картинки
	xmlHttp.onreadystatechange = function(){
		if (xmlHttp.readyState==4){
			document.getElementById('progressbar').innerHTML	=	'Завершено.<br />'+xmlHttp.responseText;
		}
	}
}

</script>
<style>
	/* Немного украшательств */
	td{
		font-family:	Tahoma;
		font-size:		11pt;
		color:			#185;
		text-align:		left;
	}
</style>
</head>
<body>
<center>
<div id="progressbar"></div>
<!-- Кстати, форму можно не делать, т.к. при отправке мы обращаемся к инпутам с помощью getElementById и отправляем с помощью аякс -->
<table>
	<tr>
		<td>Адрес начальной страницы:</td>
		<td><input type="text" size="40" id="url" value="http://" /></td>
	</tr>
	<tr>
		<td>Типы файлов:</td>
		<td><input type="text" size="10" id="types" value="doc" /></td>
	</tr>
	<tr>
		<td>Максимальное количество файлов</td>
		<td><input type="text" size="5" id="max" value="0" /></td>
	</tr>
	<tr>
		<td colspan="2"><input type="button" value="Начать" onclick="start()" /></td>
	</tr>
</table>
</center>
</body>
</html>

И обработчик (файл parser.php):

//Ставим время выполнения 10 минут
ini_set('max_execution_time', 600);
//замеряем время начала работы скрипта
$st_time	=	microtime(true);

//устанавливаем переменные...
$url		=	$_POST['url'];
$types		=	$_POST['types'];
$maxPages	=	(int)$_POST['max'];
$host		=	explode('/', substr($url, 7));
$host		=	substr($url, 0, 7).$host[0].'/';
//про последние 2 строчки подробней: таким вот образом получаем Адрес сайта (на случай, если ввели
//адрес странички сайта) - разбиваем на массив по слешу и берём первую часть...

//для удобства работы с КУРЛом, напишем простенькую функцию
//параметры: $host - адрес, $referer - откуда пришли (можно подделать, в статистике парсимого сайта будет отображаться, что мы пришли, например, с Яндекса :))
//$file	- идентификатор файла (если мы хотим скачать файл, то передаём его идентификатор)
function curl_get($host, $referer = null, $file = null){
	//инициализация curl и задание основных параметров
	$ch = curl_init($host);
	curl_setopt($ch, CURLOPT_USERAGENT, 'KOZ1024 Site Parser');
	curl_setopt($ch, CURLOPT_HEADER, 0);
	curl_setopt($ch, CURLOPT_REFERER, $referer);
	//если дали ссылку на файл
	if (!is_null($file)){
		//то устанавливаем опцию записи в файл,
		curl_setopt($ch, CURLOPT_FILE, $file);
		//и выполняем
		curl_exec($ch);
		//не забываем закрыть соединение
		curl_close($ch);
	}else{
		//если же ссылку на файл не дали, то возвращаем страничку
		ob_start();
		curl_exec($ch);
		print(curl_error($ch));
		curl_close($ch);
		return ob_get_clean();
	}
}
//получаем html-код исходной страницы
$page	=	curl_get($url);
//регулярным выражением ищем вхождение ссылок
preg_match_all('#href="([A-z0-9.-]+)"#', $page, $matches);
//получаем массив всех-всех ссылок с этой старницы
$links		=	$matches[1];
$cnt		=	0;
//цикл: пока не прошли весь массив ссылок, либо пока не скачали макс. количество файлов (не действет в случае 0)
for($i=0; ($i<sizeof($links)&&($cnt<$maxPages||$maxPages==0)); $i++){
	//если в ссылке есть нужное нам расширение
	if (strpos($links[$i], $types)!==false){
		//то открываем файл, "курлим" в него содержимое файла на сервере, закрываем, увеличиваем счётчик
		$fp		=	fopen($links[$i], 'w');
		curl_get($host.$links[$i], $url, $fp);
		fclose($fp);
		$cnt++;
	}else{
		//иначе это ещё одна ссылка, перейдём по ней, найдём все ссылки и занесём их в массив
		$page	=	curl_get($links[$i], $url);
		preg_match_all('#href="([A-z0-9.-]+)"#', $page, $matches);
		$links	=	array_merge($links, $matches[1]);		
	}
}
//замеряем время окончания работы и выводим...
$en_time	=	microtime(true);
print 'Скачано файлов: '.$cnt.'<br />Время выполнения: '.($en_time-$st_time);

Также, приведу некоторые параметры — опции курла. Применяются они, как вы могли увидеть выше, таким образом: curl_setopt(идентификатор, опция, параметр);

Опция Описание Пример
CURLOPT_UPLOAD Указываем, что мы хотим выгрузить файл на сервер. Поставтье в ненулевое значение //указываем дескриптор открытого на чтение файла, которого собираемся передать curl_setopt($ch, CURLOPT_INFILE, $fp); //указываем размер отправляемого файла curl_setopt($ch, CURLOPT_INFILESIZE, $filesize); //указываем, что файл передается методом PUT curl_setopt($ch, CURLOPT_PUT, true); //указываем, что будет производиться закачка на удаленный сервер curl_setopt($ch, CURLOPT_UPLOAD, true);
CURLOPT_INFILE Указываем дескриптор выгружаемого файла
CURLOPT_INFILESIZE Указываем размер выгружаемого файла
CURLOPT_PUT Указываем, что будем передавать методом put. Поставьте в ненулевое значение
CURLOPT_POST Указываем, что хотим отправить POST-запрос. Обычно, для стандартной формы укажите application/x-www-form-urlencoded curl_setopt($ch, CURLOPT_POST, 'application/x-www-form-urlencoded');
curl_setopt($ch, CURLOPT_POSTFIELDS, 'search=text¶m1=value2');
CURLOPT_POSTFIELDS Указываем строку, содержащую данные для передачи через POST
CURLOPT_TIMEOUT Указываем время (в секундах), по проишествии которого соединение будет оборвано
CURLOPT_RESUME_FROM Указываем смещение в байтах, с которого нужно начинать приём файла
CURLOPT_URL Указываем URL старницы (если не сделали это в функции curl_init();) $ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'http://example.com');
CURLOPT_REFERER Указываем заголовок referer (откуда перешли) curl_setopt($ch, CURLOPT_REFERER, 'http://google.com');
CURLOPT_USERAGENT Указываем заголовок UserAgent (пользовательский браузер, грубо говоря) curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows; U; Windows NT 5.1; ru; rv:1.9.0.17) Gecko/2009122116 Firefox/3.0.17')
CURLOPT_COOKIE Указываем заголовок COOKIE
CURLOPT_PROXY Указываем прокси для соединения с Интернетом (если Вы используете Интернет через прокси) curl_setopt($ch, CURLOPT_PROXY, 'username:password@192.168.0.3:3128')

Это далеко не все опции курла, только небольшая, но наиболее востребованная их часть. Более полный список ищите в мануалах...

Примечание. Будьте внимательы! На шаред-хостинге Вам, вероятно, откажут в выполении скрипта более 30 секунд, а если ваш скрипт повесит весь сервер, то Вас могут отключить! Прочтите правила

Заключение. Вот мы и написали небольшой, но тем не менее работющий парсер сайтов. По-хорошему, его можно неплохо оптимизировать, сделать более универсальным, да чего там - можно применить к нему ООП. Но цель данной статьи была - объяснить работу cURLа на примере. Надеюсь, я этой цели достиг... Удачи в освоении!

Комментарии удалены

© koz1024 2010, 2019