Добавляем PROXY для парсинга Google

Тема в разделе "Thunder 3.X", создана пользователем Firestarter, 5 июл 2016.

  1. Этот сайт использует файлы cookie. Продолжая пользоваться данным сайтом, Вы соглашаетесь на использование нами Ваших файлов cookie. Узнать больше.
  1. Firestarter

    Firestarter Администратор
    Команда форума

    26 окт 2015
    1.207
    548
    Давно просили прокси(только http) для парсеров, но так как работы там довольно много(Все парсеры нужно переписывать), пока покажу пример как добавить их в парсер гугла:

    В \plugins\Snippets.php: ищем функцию getGoogleSnippets.

    Было:

    Код:
    public function getGoogleSnippets($keyword = null, $count = 100, $lang = 'ru') {
    
            if($keyword === null){
                return null;
            }
    
            $url = 'https://www.google.com/search?q='.urlencode($keyword).'&num='.intval($count).'&lr=lang_'.trim($lang);
                       
            $options = array(
                'follow_redirects' => true,
                'useragent'=>'Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.71 Safari/537.36',
                'cookies' => $this->container['cookie']
            );
    
            $response = Requests::get($url,array(), $options);   
                  
            if($response->success === false){
    
                return null;
            }
    
            $crawler = new Symfony\Component\DomCrawler\Crawler();
    
            $crawler->addHtmlContent($response->body, 'UTF-8');
    
            $snippets = [];
    
            $urls = $crawler
                ->filter('h3.r a')
                ->extract(array('href'))
            ;
    
            $titles = $crawler
                ->filterXpath('//*[@id="rso"]/div/div/div/h3/a')
                ->slice()
                ->extract(array('_text'))
            ;
    
            $descriptions = $crawler
                ->filterXpath('//*[@id="rso"]/div/div/div/div/div/span')
                ->slice()
                ->extract(array('_text'))
            ;
    
            foreach ($titles as $key => $title) {
                $snippets[$key]['title'] = $titles[$key];
                $snippets[$key]['description'] = $descriptions[$key];
                $snippets[$key]['link'] = $urls[$key];
            }
    
            unset($response, $crawler);
    
            return $snippets;
        }
    Стало (Добавляем поддержку прокси):
    Код:
    public function getGoogleSnippets($keyword = null, $count = 100, $lang = 'ru') {
    
            if($keyword === null){
                return null;
            }
    
            $url = 'https://www.google.com/search?q='.urlencode($keyword).'&num='.intval($count).'&lr=lang_'.trim($lang);
                       
            $options = array(
                'follow_redirects' => true,
                'useragent'=>'Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.71 Safari/537.36',
                'cookies' => $this->container['cookie']
            );
    
            $proxylist = 'http://api.foxtools.ru/v2/Proxy.txt?cp=UTF-8&lang=Auto&type=HTTP&anonymity=Low&available=Yes&free=Yes&uptime=1';
    
            $proxy_cache_key = md5($proxylist);
    
            if($this->container->cache->contains( $proxy_cache_key ) ) {
    
                $proxies = $this->container->cache->fetch( $proxy_cache_key);
    
            } else {
    
                $proxies = explode(PHP_EOL, file_get_contents($proxylist));
    
                $this->container->cache->save( $proxy_cache_key, $proxies, 5*60);
    
                $proxies = $this->container->cache->fetch( $proxy_cache_key );
            }   
    
            $proxy_requests_count = 5;
    
            for ($i=0; $i < $proxy_requests_count; $i++) {
    
                $options['timeout'] = 2.5;
    
                $options['proxy'] = $proxies[array_rand($proxies)];
    
                try {
    
                    $response = Requests::get($url,array(), $options);
    
                    if( $response->success === false) {
    
                        continue;
    
                    } else {
    
                        break;
    
                    }
    
                } catch (Requests_Exception $e) {
    
                    continue;
               
                }
    
            }
    
            if(!isset($response)) {
    
                unset( $options['timeout'], $options['proxy'] );
    
                $response = Requests::get($url,array(), $options);
    
            }
                  
            if($response->success === false){
    
                return null;
            }
    
            $crawler = new Symfony\Component\DomCrawler\Crawler();
    
            $crawler->addHtmlContent($response->body, 'UTF-8');
    
            $snippets = [];
    
            $urls = $crawler
                ->filter('h3.r a')
                ->extract(array('href'))
            ;
    
            $titles = $crawler
                ->filterXpath('//*[@id="rso"]/div/div/div/h3/a')
                ->slice()
                ->extract(array('_text'))
            ;
    
            $descriptions = $crawler
                ->filterXpath('//*[@id="rso"]/div/div/div/div/div/span')
                ->slice()
                ->extract(array('_text'))
            ;
    
            foreach ($titles as $key => $title) {
                $snippets[$key]['title'] = $titles[$key];
                $snippets[$key]['description'] = $descriptions[$key];
                $snippets[$key]['link'] = $urls[$key];
            }
    
            unset($response, $crawler);
    
            return $snippets;
        }
    Где $proxylist - путь к файлу с прокси;
    $proxy_requests_count - попыток запросов через прокси, иначе парсим напрямую;
    $options['timeout'] - таймаут прокси в секундах.
    Прокси обновляются раз в 5*60 секунд.


     
  2. amness

    amness Активный Участник

    11 апр 2016
    241
    84
    Мужской
    Логигу работы поясните в двух словах.
    Сначало берётся один прокси из листа через раз в 5*60 секунд берётся другой ? При бане определённого прокси берётся другой или начинает парсить напрямую?
     
  3. Firestarter

    Firestarter Администратор
    Команда форума

    26 окт 2015
    1.207
    548
    Нет, немного не так:
    Скрипт берет случайные прокси из листа и пробует получить выдачу гугла, если не получилось пытается снова. Но раз в 3(те самые 5*60) минуты, скрипт обовляет все прокси из листа.
     
  4. amness

    amness Активный Участник

    11 апр 2016
    241
    84
    Мужской
    Понял, т.е. он берёт прокси с урл, сохраняет в файл и работает из него.Прокси там наверное уг)).Если я свой урл c проксилистом вставлю, какие-то нюансы с кодировкой страницы и т.п. есть?
     
  5. Firestarter

    Firestarter Администратор
    Команда форума

    26 окт 2015
    1.207
    548
    Тут сказать ничего не могу, пробуйте.
     
  6. Roman

    Roman Участник

    22 ноя 2015
    93
    10
    Мужской
    К 2.5 версии можно как-то добавить?
     
  7. Firestarter

    Firestarter Администратор
    Команда форума

    26 окт 2015
    1.207
    548
    К сожалению нет, там слишком все по другому.
     
  8. kibec

    kibec Участник

    2 янв 2016
    65
    6
    И тут вы не досмотрели.. А если прокси не общие, а индивидуальные с авторизацией ? )
     
  9. Firestarter

    Firestarter Администратор
    Команда форума

    26 окт 2015
    1.207
    548
    Индивидуальные с авторизацией:
    Было:
    Код:
    $options['proxy'] = $proxies[array_rand($proxies)];
    Стало:
    Код:
    $options['proxy'] = explode(',',$proxies[array_rand($proxies)]);
    Прокси должны быть в виде:
    127.0.0.1:8080,username, password
    Если в строках другой разделитель, то замените первый параметр в explode на свой разделитель.
     
  10. Art

    Art Участник

    23 фев 2017
    28
    9
    Мужской
    php\html\css developer
    #10 Art, 26 мар 2017
    Последнее редактирование: 26 мар 2017
    Тестирую на локально сервере. Вот такое иногда выдает:

    The application could not run because of the following error:

    Details
    Type: Error
    Message: Call to a member function register() on string
    File: E:\Documents\Projects\th3\vendor\rmccue\requests\library\Requests.php
    Line: 498
    Trace
    #0 E:\Documents\Projects\th3\vendor\rmccue\requests\library\Requests.php(303): Requests::set_defaults('https://www.goo...', Array, NULL, 'GET', Array)
    #1 E:\Documents\Projects\th3\vendor\rmccue\requests\library\Requests.php(194): Requests::request('https://www.goo...', Array, NULL, 'GET', Array)

    Это как то можно пофиксить?

    И на удаленном сервере протестил - эта же ошибка.
     
  11. Art

    Art Участник

    23 фев 2017
    28
    9
    Мужской
    php\html\css developer
    В общем проблема была в проксях и плохом интернете. Протестил на хороших прокси, все работает.)
    Но как избежать этих ошибок не понял. Хотелось бы их как-то обходить, чтобы не стопорился парсинг.