Версия для печати темы

Нажмите сюда для просмотра этой темы в обычном формате

DF2 :: ФОРУМЫ _ Программирование / Coding _ Как сделать Парсер на PHP

Автор: t800 04 Mar 2017, 10:18

У нас в городе есть компьютерный магазин. Заведует им дядя Стёпа. Этот магазин все знают и там покупают компьютеры. А так как теперь эра интернета, то у этого магазина тоже появился интернет магазин , через который тоже можно будет покупать. Но он пока пустой, так как он не заполнен, а так как дяде Стёпе некогда его заполнять (потому что в офисе дел полно), то он поручил мне эту задачу.

И теперь мне нужно заполнить магазин на VirtualMart3 такими же товарами как на другом сайте (из другого города) где стоит Битрикс. Я уже создал категории, начинаю добавлять к ним картинки, но с товарами сложности потому что в ручную это делать замучаешься, ибо товаров на другом магазине около 1000, и даже больше. И каждый нужно перенести и не только название и цену (и еще ее при этом умножить на разные проценты) да ещё и описания картинки в придачу. Я их уже третий день вечером после школы переношу и понял, что в ручную переносить это будет долго. Недельки 3 где-то, и мне захотелось попробовать написать скрипт чтобы автоматом перенести товары как это надо, потому что вручную заполнять оно как-то очень скучно.

Ну и у меня вопрос а как сделать такой пасер?

Автор: feanor 04 Mar 2017, 15:55

Скачиваешь страницы магазина, разбираешь при помощи XPath (на худой конец - регулярных выражений, но xpath удобнее, потому что отладчик хрома).

(буквально пару дней назад на работе была такая задача, только еще надо было еще давать аналитикам заполнять окно фильтров на сайте. Почти три дня промудохался, блин.)

Автор: t800 04 Mar 2017, 16:39

Цитата(feanor @ 04 Mar 2017, 18:55) *
Скачиваешь страницы магазина, разбираешь при помощи XPath (на худой конец - регулярных выражений, но xpath удобнее, потому что отладчик хрома).


Сейчас попгулил про XPath если правильно понял через XPath в Mozilla надо смотреть откуда что надо брать.
Ну вот я взял любой странице название товара, описание и название картинки, куда это потом сохранять в текстовый файлик? А каких брать с разных страниц и так чтоб они не перепутались? Или это без разницы в каком порядке их брать? А тогда как их вставлять в новый сайт чтобы товар их нужнного раздела был в нужнм разделе . Делать провеку по названию раздела в файлике а потом вставлять товар и скачивать картинку что по ссылке для этого раздела из файлика?

Автор: feanor 05 Mar 2017, 00:25

Как бы, тебе виднее.

Без конкретики я не могу ничего сказать по тому, как его лучше обносить; вставка - и вовсе отдельная задача, я с VirtualMart 3, чем бы оно не было, не работал.

Автор: t800 05 Mar 2017, 03:58

Так ну я нагулил какой-то скрип который вроде бы умеет парсить товары из оzоn и яндек-маркет в VirtualMart я его поставил и запустил и вроде что-то делает правда скрипту 5 лет так что наверное поэтому он ничего с оzона спарсить не может, но оно мне вроде и надо мне же надо переделать чтоб он парсил с того сайта с которо мне сказали товары взять.

Прото я посмотрел тот его модуль которы вроде для оzоn

Вот его код:

Код
<?php
    @unlink('stop.txt');
    ob_end_clean();
    require_once("config.php");
    mysql_connect($host,$login,$password);
    mysql_selectdb($database);

    #$mainstop = true;

        require_once("includes.php");

        echo "<b>".$_['menu']." OZON</b><br /><br />";

        $mass=$_GET['url'];
        
        $parse = new ozonparse();
        $parse->sleep = $_GET['sleep'];
        $parse->proxy = $_GET['proxy'];
        $parse->key = $_GET['key'];
        $parse->noimg = $_GET['noimg'];
        $parse->ceil = $_GET['ceil'];
        $parse->_ = $_;

    if(!empty($_GET['file'])) {
        $file = file_get_contents("files/".$_GET['file']);
        $strs = explode("\n",$file);
        foreach($strs as $str) {
            if(!empty($str)) {
                $_strs[] = strtolower(trim($str));
            }
        }
        
        $parse->strs = $_strs;

    }

foreach ($mass as $url)
{
$url = str_replace("%%","&",$url);
$parse->parse_list($url,$_GET['num']);
}
        



    # require_once("footer.php");
?>


И что-то не вижу а где тут назначаются поля которы надо парсить

Посмотрел код модуля который для яндекс а он почти и не отличается.


Код
<?php
    require_once("config.php");
    @unlink('stop.txt');
    mysql_connect($host,$login,$password);
    mysql_selectdb($database);
    require_once("includes.php");
    
$cou['213']='Москва';
$cou['2']='Санкт-Петербург';
$cou['65']='Новосибирск';
$cou['54']='Екатеринбург';
$cou['51']='Самара';
$cou['66']='Омск';
$cou['43']='Казань';
$cou['56']='Челябинск';
$cou['39']='Ростов-на-Дону';
$cou['172']='Уфа';
$cou['38']='Волгоград';
$cou['50']='Пермь';
$cou['62']='Красноярск';
$cou['193']='Воронеж';
$cou['194']='Саратов';
$cou['35']='Краснодар';
$cou['240']='Тольятти';
$cou['143']='Киев';
$cou['157']='Минск';
$cou['162']='Алматы';

    echo "<b>".$_['menu']." Market.yandex.ru</b><br /><br />";
    $mass=$_GET['url'];
    $parse = new yamparse();
    $parse->sleep = $_GET['sleep'];
    $parse->proxy = $_GET['proxy'];
    $parse->key = $_GET['key'];
    $parse->noimg = $_GET['noimg'];
    $parse->countname=$cou[$_GET['yacout']];
    $parse->countnum=$_GET['yacout'];
    $parse->noimg = $_GET['noimg'];
    $parse->antikey = $Config['antigate'];
    $parse->ceil = $_GET['ceil'];
    $parse->_ = $_;
    if(!empty($_GET['file'])) {
        $file = file_get_contents("files/".$_GET['file']);
        $strs = explode("\n",$file);
        foreach($strs as $str) {
            if(!empty($str)) {
                $_strs[] = strtolower(trim($str));
            }
        }
        
        $parse->strs = $_strs;
    }

    foreach ($mass as $url)
{
$url = str_replace("%%","&",$url);
    if(substr_count($url,"guru.xml")) {
        $parse->parse_list($url,$_GET['num']);
    } else {
        $parse->parse_ext($url,$_GET['num']);    
    }
    }

?>


Я сейчас хочу попробовать свой модуль это скрипта сделать чтоб он с того сайта что мне сказали парсил.
Но не могу понять куда и как поля прописывать ну или хотябы где в этих модулях прописаны поля которые скрип берет с сайтов

А сам скрипт вот он:  parser85.zip ( 660.34 килобайт ) : 3


Автор: t800 20 Mar 2017, 07:52

Хммм... короче поставил этот скрип, настроил, скрипт работает но ничего не парсит даже с тех сайтов что у нем прописаны. Наверное слишком старый. Я посмотрел код этого старого скрипта и понял что проще будет написать новый чем разобраться почему не работает этот который старый.

Автор: t800 20 Mar 2017, 12:19

Так я нашел на SF.net библиотеку PHP Simple HTML DOM Parser см. https://sourceforge.net/projects/simplehtmldom/

Скчал, положил на своем сайте в каталог /parser/library

Потом в каталоге parser создал файл test0.php c таким вот кодом

Код
<?php

echo '<html xml:lang="ru-ru" lang="ru-ru" >';
echo '<head><meta http-equiv="content-type" content="text/html; charset=utf-8" /></head>';

//подгружаем библиотеку
require_once 'library/simplehtmldom.php';

//создаём новый объект
$html = new simple_html_dom();
//загружаем в него данные
$html = file_get_html('http://site.ru/');
//находим все ссылки на странице и...
if($html->innertext!='' and count($html->find('a'))) {
foreach($html->find('a') as $a){
//... что то с ними делаем
echo 'Ура! Я что-то спарсил..<br/>';
}
}
//освобождаем ресурсы
$html->clear();
unset($html);
?>


Запустил это файл через браузер у скрипт мне выдал вот что:

http://wiki.kvkozyrev.org/parser/test0.php

Автор: t800 20 Mar 2017, 22:35

Так. Вот вроде из примера сделал скрипт который спарсил страницу с товаром

Код
<?php
echo '<html xml:lang="ru-ru" lang="ru-ru" >';
echo '<head><meta http-equiv="content-type" content="text/html; charset=utf-8" /></head>';

//подгружаем библиотеку
require_once 'library/simplehtmldom.php';

//создаём новый объект
$html = new simple_html_dom();
//загружаем в него данные
$html = file_get_html('http://site.ru/catalog/ibp_akkumulyatory_i_stabilizatory/batarei_dlya_ibp/akkumulyatornye_batarei_dlya_ups_svc_12v_12_ach_razmer_v_mm_150_98_95/');

//находим путь категории  на странице ...

foreach($html->find('ul[class=breadcrumb-navigation]') as $element) echo $element->plaintext . '<br>';

echo '<br>';

// нахожим название

foreach($html->find('h1[class=header_grey]') as $element) echo $element->plaintext . '<br>';

echo '<br>';


// находим цену

foreach($html->find('div[class=item_current_price]') as $element) echo $element->plaintext . '<br>';

echo '<br>';


// находим картинку

foreach($html->find('a[class=fancy bx_bigimages_aligner]') as $element) echo '<img src="' . $element->href . '"><br>';

echo '<br>';

// находим  краткие характеристики

foreach($html->find('div[class=props_top]') as $element) echo $element->plaintext . '<br>';

echo '<br>';

// находим полные характеристики

foreach($html->find('div[class=left_prop]') as $element) echo $element->plaintext . '<br>';

echo '<br>';

foreach($html->find('div[class=left_value]') as $element) echo $element->plaintext . '<br>';


//освобождаем ресурсы
$html->clear();
unset($html);
?>


Вот что получилось http://wiki.kvkozyrev.org/parser/test6.php

А как теперь сделать чтобы он парсил не одну страницу а все страницы с товарами?
Про это в примерах я ничего не нашел.

Автор: t800 02 Apr 2017, 23:55

Фух вроде доделал скрипт. barb_metal.gif barb_metal.gif barb_metal.gif


Код
<?php
// Задаем заголовки чтобы по русски отображалось нормально
echo '<html xml:lang="ru-ru" lang="ru-ru" >';
echo '<head><meta http-equiv="content-type" content="text/html; charset=utf-8" /></head>';
echo "Парсер от t800 :-) <br/><br/>";


set_time_limit(0); // это для того чтобы скрипт не отвалился через 30 секунд

//подгружаем библиотеку Simple HTML Dom
require_once 'library/simplehtmldom.php';

/* Теперь сам скрипт */


$i=1;

// Указваем количество страниц сколько  хочем спарсить
$n=5;

// Пишем дату сверху в файл куда пишем то что будем парсить
$time = date('Y:m:d:H:i');
$fp = fopen("parse.txt", "w"); // Открываем файл в режиме записи
$test = fwrite($fp,$time . "\r\n");
fclose($fp); //Закрытие файла

// Указываем адрес карты сайта (файла sitemap.xml) откуда берем ссылки страниц которые надо парсить

$sitemap = "http://site.ru/sitemap.xml";

// загружаем файл sitemap

$xml = simplexml_load_file($sitemap);

// Извлекаем ссылки из файла sitemap.xml

foreach ($xml->url as $url_list) {
    $url = $url_list->loc;

// вызываем нашу функцию parse() с указанием url страницы которую надо спарсить

    parse($url);

// Выводим инфу о загрузке
        echo " ***  Загружено: ".$i." из ".$n." страниц *** \r\n ";
        echo "<br>";
        echo str_pad('',4096)."\n";
        echo str_pad('',4096)."\n";
        flush();
// Тут проверка условия  на то сколько спрарсили страниц и выход из скрипта если уже спарсили сколько задано
        if($i++>=$n){
                echo " *** Готово! *** ";
                exit;
                }
}

// Здесь парсим страницу с url  нашей фукцией  parse()
// А это код нашей функция parse()

function parse($url)
{

$data = @file_get_contents($url); // собачка нужна в если сервер нам вернул 404, это вызовет Warning:, поэтому экранируем ошибки
if(trim($data)=='')return false; // бывает что сайт недоступен, тогда страницy не грузим а выходим из функции

//создаём новый объект
$html = new simple_html_dom();
//загружаем в него данные
$html = @file_get_html($url); // собачка нужна в если сервер нам вернул 404, это вызовет Warning:, поэтому экранируем ошибки

//проверяем что спарсили страничу с товаром (проверку делаем по цене) если цены нету то выходим из функции

$ret = $html->find('div[class=item_current_price]', 0);
if ($ret==null) return false;

//находим путь категории  на странице ...

foreach($html->find('ul[class=breadcrumb-navigation]') as $ul)
{
        foreach($ul->find('li') as $li)
        {
                foreach($li->find('a') as $a)
                {
                echo $a->plaintext . '/';
                $catalog = $a->plaintext . '/';
                $fp = fopen("parse.txt", "a"); // Открываем файл в режиме дописывания
                $test = fwrite($fp, $catalog ); // Запись в файл
                fclose($fp); //Закрытие файла
                }

       }
}


//echo '<br/>';

$fp = fopen("parse.txt", "a"); // Открываем файл в режиме дописывания

// находим название

foreach($html->find('h1[class=header_grey]') as $element) echo $element->plaintext;

//echo '<br>';

$test = fwrite($fp, $element->plaintext ); // Запись в файл
if ($test) echo '';
else echo 'Ошибка при записи в файл.';


// находим цену

foreach($html->find('div[class=item_current_price]') as $element) echo '';

$test = fwrite($fp, $element->plaintext ); // Запись в файл

if ($test) echo '';
else echo 'Ошибка при записи в файл.';


// находим картинку

foreach($html->find('a[class=fancy bx_bigimages_aligner]') as $element) echo '';

$url_img = "http://site.ru/" . $element->href;

// извелкаем имя файла картинки из url картинки
$file_name= substr($url_img, strrpos($url_img,"/")+1, strlen($url_img)-strrpos($url_img,"/"));  //Retrive file name from url

// задаем папку куда картинку сохранять
$img_path = "./images/".$file_name;

$test = fwrite($fp, $img_path ); // Запись в файл
if ($test) echo '';
else echo 'Ошибка при записи в файл.';

//  Закачиваем и сохраняем изображение

grab_image($url_img,$img_path);

// находим  краткие характеристики

foreach($html->find('div[class=props_top]') as $element) $test = fwrite($fp, $element); // Запись в файл

// находим полные характеристики

foreach($html->find('div[class=left_prop]') as $element)  $test = fwrite($fp, $element); // Запись в файл

foreach($html->find('div[class=left_value]') as $element)  $test = fwrite($fp, $element); // Запись в файл


// Записываем концы строк

$test = fwrite($fp, "\r\n" );
fclose($fp); //Закрытие файла

//в конце освобождаем ресурсы (не знаю зачем это надо, но говорят, что надо, иначе скрипт может зависнуть)
$html->clear();
unset($html);

}

// Это функция grub_image() че картинки скачивает сurl-ом  и сохраняет  (взята из комментариев на Stack Overflow)
// ЗЫ  сurl-ом потому что curl-ом быстрее скачивается

function grab_image($url,$saveto){
    $ch = curl_init ($url);
    curl_setopt($ch, CURLOPT_HEADER, 0);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_BINARYTRANSFER,1);
    $raw=curl_exec($ch);
    curl_close ($ch);
    if(file_exists($saveto)){
        unlink($saveto);
    }
    $fp = fopen($saveto,'x');
    fwrite($fp, $raw);
    fclose($fp);
}

?>


Скрипт работает вот так:

http://wiki.kvkozyrev.org/parser/parser7.php

Форум Invision Power Board (http://nulled.cc)
© Invision Power Services (http://nulled.cc)