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

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

Начинающий программист зачастую пугается многих страшных слов, когда ему советуют для определённой задачи использовать что-либо. В этой статье я хочу развеять страх перед таким словом, как 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а на примере. Надеюсь, я этой цели достиг... Удачи в освоении!

Следующая статья: PHP sendmail: отправка почты с вложениями посредством PHP

Вы нашли то, что искали? Да  Нет

Вам понравилась статья? Да  Нет

Комментарии:
 |  Следующая страница »

Rashid 15.03.2010 13:31

А можно парсер написать, чтобы он находил номера телефонов в доске объявлений и сохранял их в БД или в файл? доска объявлений: kolesa.kz ответ на: (***)

alexandronchik 18.04.2010 16:32

не работает!(

koz1024 19.04.2010 09:58

alexandronchik, что именно у Вас не работает? Парсер проверялся в боевых условиях не один раз.
Сообщите, пожалуйста, подробные данные о выводимых ошибках, страницу, которую парсите и т.д. Можно на мыло: koz1024 собака mail.ru

alexandonchik 19.04.2010 21:05

ну вот создал я файлик index.html, туда первую часть кода, parser.php - туда вторую часть кода, воот, затем пишу, в первое поле, например: "http://www.xa-xa.org/2008/09/15/prikolnye-fotki.html" во второе: "jpg" в третье: "10" хм, ничего не парсит, как я понял должно выкидывать все в корневую папку.

koz1024 21.04.2010 10:03

alexandonchik, да, Вы правы, этот парсер немножко для другого предназначался - искать ссылки на файлы, и скачивать их.
Совсем немного изменив файл parser.php, можно получить то, что Вам нужно. Вот, держите, сделано специально для Вас :) парсер
Чуть позже добавлю это в статью

koz1024 21.04.2010 10:06

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

Wap-Style 28.07.2010 11:40

У меня парсер не работает. Не могу скачать файлы формата 3gp. Как быть? Что делать? Помогите пожалуйста.

koz1024 03.08.2010 12:27

Wap-Style, подробней, пожалуйста: покажите сайт, с которого скачиваете, что пишет парсер и т.п.
Можно написать мне на мыло: koz1024 собака mail.ru
P.S. Пардон за оперативность ответа - уехал на моря, читаю с телефона...

Wap-Style 03.08.2010 19:09

Я уже разобрался написал свой парсер правда без curl, но я не растроился я в первый раз в жизни написал такой скрипт. Жаль у вас аськи нет я бы тогда подробно смог узнать у вас всё на тему парсеров.

koz1024 05.08.2010 12:34

Wap-style, приятно видеть, когда люди сами в чем-то разбираются!
почему-же, аська у меня есть (загляните на страницу Контакты) - правда, я буду там (в аське) только во вторник...

Комментарии:
 |  Следующая страница »

Оставить комментарий
Никнейм:
Комментарий:
Ваш комментарий: