Google Thumbnail: Получаем миниатюры сайтов

в 2:23, , рубрики: Google, image, thumbnail, превью, метки: , , ,

Думаю все знают что в поиске Google можно предварительно просмотреть сайт открыв его превью.
Google Thumbnail: Получаем миниатюры сайтов
Сегодня поделюсь с вами одним из методов получения данного изображения.

Не так давно писал одну вещь(вскоре с вами поделюсь), для себя, и мне требовалось получить превью сайта, любого.

Было несколько вариантов:
— писать свой генератор превьюшек, для себя понимаю это как — скрипт должен открывать страницу, фотографировать ее, и сохранять изображение, а нужно ведь всю страницу с отработанными javascript, как я понял нужно неплохо расширить сервер дополнительными модулями и прочим, данный метод меня не устраивает.
— далее взгляд пал на готовые решения, разнообразные ресурсы предлагающие api для получения превью сайтов, но отдаваться на волю неизвестному ресурсу, та и не везде получаешь свободу, решено было отложить, а в дальнейшем и отказаться, от этого подхода
— далее пришел на помощь wordpress, а точнее сервис mShots(можно прочесть к примеру здесь), но сервис в любом случае возвращает изображение, что не дает проверить его отсутствие(кому потребуется могу поделится моим решением проверки отсутствия изображения), а так же требуется некоторое время для создания превью, и сервис никак об этом не оповещает, кроме как возвращает в любом случае gif preloader.

На последнем методе было решено остановится, и продолжить поиски метода более стабильного. Поиски проходили в Google Seach и трудно было не обратить внимания на то что он предоставляет скриншот сайта(как выяснилось, получает он их из своего кеша), и тут пришла мысль — «А почему бы и нет».
Так начался поиск способа получить изображения от google.

Первым делам посмотрел запрос:

Google Thumbnail: Получаем миниатюры сайтов

Как видите ничего радостного, куча непонятных параметров.
Не буду описывать каждый параметр, притом не все знаю, скажу лишь что «j» и «b» можно смело удалить, а «а» — это у нас уникальный трехзначный хэш, который, как выяснилось, встраивается в html разметку страницы, откуда его и можно получить, распарсив ее.

Решил опробовать я данный подход, логика была следующая:
— осуществляем поиск, в нашей задаче требуется найти сайт, поэтому ищем по запросу site:http://domain.zone
— парсим полученное и находим наши хеш и url
— формируем нужный запрос и получаем искомое

Все вроде бы логично, поэтому приступил к работе.
Волей судьбы и недостатком времени отложил данную работу и забыл про нее до сегодняшнего вечера,
а напомнило про нее мне ресурс goo.gl, а точнее новый дизайн, и новые функции, в том числе превью страницы к которой мы хотим получить короткий url. Да, для тех кто не знает goo.gl предоставляет возможность получить короткий url.

Решил поискать информацию по запросу «clients1.google.com/webpagethumbnail», на данный адрес ссылается google seach для получения скриншотов сайтов, и наткнулся на вот эту статью, здесь уже описан реализованный метод, который хотел, изначально, воплотить я.

Немного расстроенный, и в то же время рад что есть уже готовое для моей плюшки, вернулся с интересом к goo.gl, здесь заглянуть в отправляемые запросы, и что же я вижу:
Google Thumbnail: Получаем миниатюры сайтов

Тут уже нет страшных параметров, есть url api нашей сокращалки, и есть два параметра:
— security_token — как я понял необязательный параметр (исправьте меня если я не прав)
— url — и адрес по которому хотим получить информацию

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

header('Content-Type: text/html; charset=utf-8');//устанавливаем кодировку
define('URL_API', 'http://goo.gl/api/shorten');//определяем константу с адрессом откуда будем получать данные

/*
 * Функция служит для отправки запроса на нужный адресс
 * 
 * @param string $wab_page 
 *      url страницы, привью которой хотим получить
 * @param string $url  
 *      url отправки запроса 
 * @param boolean $header 
 *      определяет получить возвращаемые значения или только заголовки
 * 
 * @return boolean or decode json 
 *      возвращает либо true, при $header=TRUE и существовании файла,
 *      или ответ сервера в формате decode json
 */
function http_request($wab_page, $url=URL_API, $header=FALSE) {
    $ch = curl_init();//инициализируем сеанс
    curl_setopt($ch, CURLOPT_HEADER, $header);//включаем/выключаем вывод заголовков 
    curl_setopt($ch, CURLOPT_NOBODY, $header);//включаем/выключаем вывод тела ответа 
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE);//следуем всем заголовкам "Location: "
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);//теперь curl вернет нам ответ, а не выведет
    if(!$header){//проверяем хотим мы получить только заголовки или нет, если нет то
        curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/535.7 (KHTML, like Gecko) Chrome/16.0.912.77 Safari/535.7');//прикидываемся браузером
        curl_setopt($ch, CURLOPT_POST, TRUE);//говорим что хотим передать данные методом POST
        curl_setopt($ch, CURLOPT_POSTFIELDS, 'url='.urlencode($wab_page).'&security_token=');//устанавливаем переменные, которые будут переданные по методу post
    }else{//если да то
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);//останавливаем curl от проверки сертификата
    }
    curl_setopt($ch, CURLOPT_URL, $url);//уcтанавливаем урл, к которому обратимся
    $response = curl_exec($ch);//выполняем запрос curl
    curl_close($ch);//завершает сеанс curl и освобождает все ресурсы
    if($header){//если получаем только заголовки, то
        if(strpos($response, "200 OK")!==false)//проверяем код статуса, если 200 то все ок
                return true;//возвращаем положительный ответ
    }else//если хотим ответ, то
        return json_decode($response);//возвращаем decode json строку с ответом

}

$wab_page='http://b-d.com.ua/';//картинку какого сайта хотим получить
$request=http_request($wab_page);//делаем запрос к гуглу
if($request){//если что то пришло, то
    $img=$request->preview_url;//получаем url картинки
    $short_url=$request->short_url;//получаем короткий линк сайта
    if(http_request(null,$img,true)){//проверяем наличие изображения, если есть
        echo $wab_page.' - <a href="'.$short_url.'">'.$short_url.'</a>
<img src="'.$img.'">';//выводим данные
    }else{//если нет изображения
        echo $wab_page.' - <a href="'.$short_url.'">'.$short_url.'</a>
 что то нет желанной картинки у гугла';//выводим данные
    }
}else{
    echo 'Ошибка запроса =(';
}

Откомментировал весь код, что бы было понятно что я здесь творю. Файлом скачать можно здесь.

Коротко опишу:
— первым делом делаем запрос по адресу api «goo.gl/api/shorten», в ответ получаем json строку с информацией: «short_url», «long_url»,«creation_time»,«preview_url»
— далее проверяю существование изображения(т.к., на сколько я понял, возвращается путь к изображению всегда), проверяя заголовки на статус 200
— если все хорошо то отдаем картинку, не все хорошо сообщаем об этом

Чем мне нравится такой подход больше всех остальных:
— Я завишу только от гугла, вряд ли он просто закроется, или перестанет работать, как сторонний ресурс, с другой стороны он может прикрыть такую возможность получения превью(но на этот случай у меня есть mShots)
— Данный подход быстрее, и короче по коду, чем делать запросы к поисковику и парсить страницы
— И тут я могу еще получить короткий адресс что для моей задачи является положительным дополнением

К сожалению тестовую страницу не сделал, боюсь хостинг не выдержит, если кто то может предложить где можно разместить страницу, с радостью последую совету.

На этом все, надеюсь многим будет полезна информации, догадываюсь где сразу найдут многие применении.

P.S. Жду любых исправлений и дополнений, в особенности интересует как можно улучшить мой существующий код, заранее прошу прощение за возможные неточности и особенно орфографию, время суток сказывается.

Автор: Bookin

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js