Как через CURL получить страницу яндекс выдачи

Тема в разделе "Как сделать...", создана пользователем jabbaxatt, 18 фев 2015.

  1. jabbaxatt

    jabbaxatt Добрый модератор

    Moderator
    Регистр.:
    21 янв 2009
    Сообщения:
    878
    Симпатии:
    411
    Как через CURL получить страницу яндекс выдачи?

    Как не пробую - не получается, примеры с интернета тоже не работает.

    Т.е. он всегда, сразу, 100% случаев выдаёт страницу с капчёй. При этом через браузер с того же компа - всё нормально ищется. Т.е. у меня проблема с эмуляцией запроса из браузера, а не с тем что мой IP забанен.

    Есть у кого пример рабочего запроса на PHP + Curl, что-бы получить страницу выдачи яндекса по запросу?
     
  2. Q_BASIC

    Q_BASIC

    Регистр.:
    30 ноя 2013
    Сообщения:
    352
    Симпатии:
    223
    Можно API использовать https://tech.yandex.ru/xml/
     
  3. jabbaxatt

    jabbaxatt Добрый модератор

    Moderator
    Регистр.:
    21 янв 2009
    Сообщения:
    878
    Симпатии:
    411
    Нет, не подходит. Нужна именно выдача, а не XML.
     
  4. murlo

    murlo Создатель

    Регистр.:
    8 июн 2006
    Сообщения:
    34
    Симпатии:
    33
    Заголовки
    PHP:
    $header = array(
      
    'User-Agent: Opera/9.80 (Windows NT 6.1; WOW64; U; MRA 5.9 (build 4871); ru) Presto/2.10.289 Version/12.02',
      
    'Accept: text/html, application/xml;q=0.9, application/xhtml+xml, image/png, image/webp, image/jpeg, image/gif, image/x-xbitmap, */*;q=0.1',
      
    'Accept-Language: ru-RU,ru;q=0.9,en;q=0.8',
      
    //'Accept-Encoding: gzip, deflate',
      
    'Connection: Keep-Alive',
    );
    $ch curl_init('http://yandex.ru/yandsearch?text=1111111111');
    curl_setopt($chCURLOPT_RETURNTRANSFER1);
    curl_setopt($chCURLOPT_HTTPHEADER$header);
    $result curl_exec($ch);
    curl_close($ch);
    print_r($result);
    UP. Проверил без заголовков
    PHP:
    $ch curl_init('http://yandex.ru/yandsearch?text=1111111111');
    curl_setopt($chCURLOPT_RETURNTRANSFER1);
    $result curl_exec($ch);
    Нормально отработало, без капчи. Видимо что то с вашим IP))
    Но в любом случае. Делайте максимально естественней. Заголовки. Правильный реферер, cookie. Желательно прокси.
     
    Последнее редактирование: 19 фев 2015
    jabbaxatt нравится это.
  5. cyber_punker

    cyber_punker Создатель

    Регистр.:
    12 ноя 2014
    Сообщения:
    6
    Симпатии:
    10
    Я бы еще добавил что-то типа

    PHP:
    $agents = array(
        
    'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.7; rv:7.0.1) Gecko/20100101 Firefox/7.0.1',
        
    'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.9) Gecko/20100508 SeaMonkey/2.0.4',
        
    'Mozilla/5.0 (Windows; U; MSIE 7.0; Windows NT 6.0; en-US)',
        
    'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_7; da-dk) AppleWebKit/533.21.1 (KHTML, like Gecko) Version/5.0.5 Safari/533.21.1'
    );
    или

    Код:
    $agents = explode("\n", file_get_contents(https://raw.githubusercontent.com/cvandeplas/pystemon/master/user-agents.txt));
    
    а потом так:
    Код:
    curl_setopt($ch,CURLOPT_USERAGENT,$agents[array_rand($agents)]);
    
    Но не плохо бы и прокси прикрутить, это очень просто.
     
    jabbaxatt нравится это.
  6. warg

    warg Постоялец

    Регистр.:
    26 июн 2007
    Сообщения:
    122
    Симпатии:
    122
    Еще немаловажный момент - частота запросов в интервал времени, при превышении происходит блокировка,
    поэтому между запросами нужно ставить задержку.
    Также яндекс насколько я понял сопоставляет сессии,
    то есть если с одного IP идут запросы с разными куками - тоже возможен блок.
     
    rebux и jabbaxatt нравится это.
  7. cyber_punker

    cyber_punker Создатель

    Регистр.:
    12 ноя 2014
    Сообщения:
    6
    Симпатии:
    10
    Да, можно привязать файлы куков к ip и user-agent.
    Но лучше про тестить, часто оказывается что все на много проще :)
     
    jabbaxatt нравится это.
  8. jabbaxatt

    jabbaxatt Добрый модератор

    Moderator
    Регистр.:
    21 янв 2009
    Сообщения:
    878
    Симпатии:
    411
    Всем спасибо. Но я уже отступил от своего плана и начал писать это на Delphi. Тамошний TWebBrowser позволяет нормально ходить по страничкам яндекса (имитируя некрофила со старым IE) и сохранять HTML код. Пару сотен страниц прогнал - капчи не выдаёт. Не знаю как поведёт себя на тысячах, но пока выглядит как более менее перспективный путь решения.

    Оно конечно будет десктоп, а не сервер, но мне не критично.

    Впрочем - если у кого ещё есть мысли или рабочий код - буду рад видеть их в этой теме.
    Ибо на PHP у меня так и не получилось.
     
    Последнее редактирование: 20 фев 2015
    latteo нравится это.
  9. latteo

    latteo Эффективное использование PHP, MySQL

    Moderator
    Регистр.:
    28 фев 2008
    Сообщения:
    1.405
    Симпатии:
    1.185
    Попробуй selenium, работать с ним можно из любого популярного ЯП
     
    jabbaxatt нравится это.
  10. cyber_punker

    cyber_punker Создатель

    Регистр.:
    12 ноя 2014
    Сообщения:
    6
    Симпатии:
    10
    Ну было бы время больше можно было бы доделать.
    PHP:
    <?php
    define
    ('DOMAIN','yandex.ua'); // Важено домен
    define('SCHEME','http://');
    define('NUMDOC','50');
    define('SPRAVKA''dD0xNDI0NDQ5NjcwO2k9OTMuNzMuNTAuMjIzO3U9MTQyNDQ0OTY3MDE4NjcyNTk5MjtoPWZjODIyZTQxZTdiNmY3ZTI1ODRhMzk3ZjIwZWU2OWI2'); // Этот код можно получить если пройти капчу. Я удмаю можно сгенерить его самому. Это обычный base64
    // t=UNIX_TIMESTAMP;i=ВАШ_IP;u=1424447588654410059;h=a9251aa16f61cdf3763cc5b1c28bff88
    // Нужно только узнать как генерится u и хеш. Просто впадло ковырять. Этот код можно получить и долго рубить. Его так же можно получить если пройти капчу. По факту можно подключить антикапчу, эта капча вылазит редко если запрос подписан

    $region 143// Киев, 213 Москоу
    $query 'парсер яндекса';
    $url SCHEME DOMAIN '/yandsearch?text='urlencode($query) ."&lr={$region}&numdoc=" NUMDOC;

    function 
    get_page($url)
    {

        
    $ch curl_init();

        
    $headers = array(
                   
    'Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.6,en;q=0.4,uk;q=0.2',
                   
    'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.115 Safari/537.36',
                   
    'Cookie: spravka=' SPRAVKA ';'// было бы больше времени, можно разобраться как получить автоматом.
                
    );

        
    $options = array(
            
    CURLOPT_TIMEOUT => 15,
            
    CURLOPT_RETURNTRANSFER => TRUE,
            
    CURLOPT_FOLLOWLOCATION => TRUE,
            
    CURLOPT_URL => $url,
            
    CURLOPT_HTTPHEADER => $headers,
        );
              
        
    curl_setopt_array($ch$options);
        
    $data curl_exec($ch);
      
        
    curl_close($ch);
        return 
    $data;
    }

    $page get_page($url);

    libxml_use_internal_errors(true);
    $dom = new DOMDocument();
    $dom->preserveWhiteSpace false;
    $dom->resolveExternals false;
    $dom->validateOnParse false;
    $dom->loadHTML($page);
    $xpath = new DOMXpath($dom);

    $serp_items $xpath->query('//div[contains(@class, "serp-block") and not(contains(@class, "-adv"))]//*[contains(@class, "serp-item__wrap")]');

    $links = array();

    foreach (
    $serp_items as $k=>$item)
    {
        
    $_tmp = array();
        
    $header_obj $xpath->query('./h2'$item)->item(0);
      
        
    $_tmp['position'] = $k+1;
      
        
    $link_obj $xpath->query('./a'$header_obj)->item(0);
        
    $_tmp['url'] = $link_obj->getAttribute('href');
        
    $_tmp['url_text'] = trim(preg_replace('/\s+/i'' '$link_obj->nodeValue));
      
        
    $links[] = $_tmp;
    }

    var_dump($links);
    ?>
    Просто нет времени и особого желания)

    Попробовал еще так

    PHP:
    <?php
       
    define
    ('DOMAIN','yandex.ua'); // Важено домен
    define('SCHEME','http://');
    define('NUMDOC','50');
    define('SPRAVKA'''); // Этот код можно получить если пройти капчу. Я удмаю можно сгенерить его самому. Это обычный base64
    // t=UNIX_TIMESTAMP;i=ВАШ_IP;u=1424447588654410059;h=a9251aa16f61cdf3763cc5b1c28bff88
    // Нужно только узнать как генерится u и хеш. Просто впадло ковырять. Этот код можно получить и долго рубить. Его так же можно получить если пройти капчу. По факту можно подключить антикапчу, эта капча вылазит редко если запрос подписан

    $region 143// Киев, 213 Москоу
    $query 'парсер яндекса';
    $url SCHEME DOMAIN '/yandsearch?text='urlencode($query) ."&lr={$region}&numdoc=" NUMDOC "&ncrnd=" rand(100,999);

    function 
    get_page($url)
    {

        
    $ch curl_init();

        
    $headers = array(
                    
    'Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.6,en;q=0.4,uk;q=0.2',
                    
    'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.115 Safari/537.36',
    //                 'Cookie: spravka=' . SPRAVKA . ';', // было бы больше времени, можно разобраться как получить автоматом.
                
    );

        
    $options = array(
            
    CURLOPT_TIMEOUT => 15,
            
    CURLOPT_RETURNTRANSFER => TRUE,
            
    CURLOPT_FOLLOWLOCATION => TRUE,
            
    CURLOPT_URL => $url,
            
    CURLOPT_HTTPHEADER => $headers,
        );
               
        
    curl_setopt_array($ch$options);
        
    $data curl_exec($ch);
       
        
    curl_close($ch);
        return 
    $data;
    }

    $page get_page($url);

    libxml_use_internal_errors(true);
    $dom = new DOMDocument();
    $dom->preserveWhiteSpace false;
    $dom->resolveExternals false;
    $dom->validateOnParse false;
    $dom->loadHTML($page);
    $xpath = new DOMXpath($dom);

    $serp_items $xpath->query('//div[contains(@class, "serp-block") and not(contains(@class, "-adv"))]//*[contains(@class, "serp-item__wrap")]');

    $links = array();

    foreach (
    $serp_items as $k=>$item)
    {
        
    $_tmp = array();
        
    $header_obj $xpath->query('./h2'$item)->item(0);
       
        
    $_tmp['position'] = $k+1;
       
        
    $link_obj $xpath->query('./a'$header_obj)->item(0);
        
    $_tmp['url'] = $link_obj->getAttribute('href');
        
    $_tmp['url_text'] = trim(preg_replace('/\s+/i'' '$link_obj->nodeValue));
       
        
    $links[] = $_tmp;
    }

    var_dump($links);
    вроде работает. В общем нужно разбираться, может когда-то будет такая задача то выложу)
     
    Последнее редактирование: 20 фев 2015
    rebux, latteo и jabbaxatt нравится это.