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, что именно у Вас не работает? Парсер проверялся в боевых условиях не один раз.
Сообщите, пожалуйста, подробные данные о выводимых ошибках, страницу, которую парсите и т.д. Можно на мыло:
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, приятно видеть, когда люди сами в чем-то разбираются!
почему-же, аська у меня есть (загляните на страницу Контакты) - правда, я буду там (в аське) только во вторник...
Комментарии:
| Следующая страница »