Парсер сайта на PHP
Рассмотрим создание парсера на PHP с использованием языка запросов xPath.
Данные будут браться с одного популярного аниме-сайта (animevost.org). Нас будут интересовать следующие данные: название, год выхода, жанр, тип, количество серий, режиссер и описание. В результате использования xPath у нас отпадает необходимость в регулярных выражениях. Все это приятно отразится на скорости работы скрипта.
Листинг файла index.php.
<?php
set_time_limit(0);libxml_use_internal_errors(true);
$start = microtime(true);
$url = 'http://animevost.org/zhanr/';
$refererUrl = 'http://animevost.org';
$nPagePause = 4;$data = curlGetContents($url, $refererUrl);
if ($data['code'] == 200){
$doc = new DOMDocument();
$doc->loadHTML($data['data']);
$xPath = new DOMXpath($doc);$startPage = 1;
$endPage = parseNumberLastPage($xPath);echo 'Парсер начал работу...<br>';
while($startPage <= $endPage){
$link = "{$url}page/$startPage/";$data = curlGetContents($link, $refererUrl);
if ($data['code'] == 200){
$doc = new DOMDocument();
$doc->loadHTML($data['data']);
$xPath = new DOMXpath($doc);$data = [];
// Название
$d1 = parseContent($xPath, "//div[@id='dle-content']/div/div/h2/a");
// Год выпуска
$d2 = parseContent($xPath, "//div[@id='dle-content']/div[@class='shortstory']/div[@class='shortstoryContent']/table/tr/td/p", 'Год выхода:', 12);
// Жанр
$d3 = parseContent($xPath, "//div[@id='dle-content']/div[@class='shortstory']/div[@class='shortstoryContent']/table/tr/td/p", 'Жанр:', 6);
// Тип
$d4 = parseContent($xPath, "//div[@id='dle-content']/div[@class='shortstory']/div[@class='shortstoryContent']/table/tr/td/p", 'Тип:', 5);
// Количество серий
$d5 = parseContent($xPath, "//div[@id='dle-content']/div[@class='shortstory']/div[@class='shortstoryContent']/table/tr/td/p", 'Количество серий:', 18);// Режиссёр
$d6 = parseGetProducer($xPath);// Описание
$d7 = parseContent($xPath, "//div[@id='dle-content']/div[@class='shortstory']/div[@class='shortstoryContent']/table/tr/td/p", 'Описание:', 10);// Массив для записи в файл
$c = count($d1);
for($i=0;$i<$c;$i++){
$data[] = implode('|', [$d1[$i], $d2[$i], $d3[$i], $d4[$i], $d5[$i], $d6[$i], $d7[$i]]);
}unset($d1, $d2, $d3, $d4, $d5, $d6, $d7, $c);
file_put_contents('data/' . str_replace(['http:', 'https:', '//', '/', '.'], ['', '', '', '-', '_'], rtrim($link, '/')) . '.txt', implode("\n", $data));
// Каждую n-страницу делаем паузу в 3 сек.
if ($startPage % $nPagePause == 0){
sleep(3);
}} else {
file_put_contents('data/errors.txt', date('d-m-Y H:i:s', time()) . ' Страница недоступна: ' . $data['errors'][0][1] . "\n", FILE_APPEND);
}$startPage++;
}echo 'Парсер завершил работу за ' . round(microtime(true) - $start, 1) . ' сек.<br>';
} else {
die('Что-то пошло не так');
}/** Функции */
/**
* Прочесть содержимое файла в строку при помощи cUrl
*
* @param $pageUrl Ссылка-источник
* @param $baseUrl Ссылка referer
* @param int $pauseTime Пауза между запросами
* @param bool $retry Разрешить / не разрешить повторение
* @return mixed
*/
function curlGetContents($pageUrl, $baseUrl, $pauseTime = 4, $retry = true) {
$errors = [];$ch = curl_init();
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt ($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt ($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_USERAGENT, getRandomUserAgent());curl_setopt($ch, CURLOPT_URL, $pageUrl);
curl_setopt($ch, CURLOPT_REFERER, $baseUrl);curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
$response['data'] = curl_exec($ch);
$ci = curl_getinfo($ch);
if($ci['http_code'] != 200 && $ci['http_code'] != 404) {
$errors[] = [1, $pageUrl, $ci['http_code']];if($retry) {
sleep($pauseTime);
$response['data'] = curl_exec($ch);
$ci = curl_getinfo($ch);if($ci['http_code'] != 200 && $ci['http_code'] != 404){
$errors[] = [2, $pageUrl, $ci['http_code']];
}
}
}