27 Август 2007...07:02

В продолжение темы про YouTube

Jump to Comments

Когда-то давным-давно, аж 22 июня 2007 года, на блоге одного хорошего человека появился занятный скрипт, который позволяет получать прямые ссылки на flv-файлы с YouTube для дальнейшего их скачивания себе локально (не мне, видать, одному надоело разгребать кеш Оперы в поисках скачанных флешек :-)). Идея была классной, но скрипт почему-то работать отказался. Пришлось долго и муторно копаться. Результатом мытарств стала пара классов, написанных на PHP5 (на баяне не играюна PHP4.x, уж извините, не пишу: двадцать первый век на дворе, шестая версия на подходе, а пятой и вообще четвертый год пошёл). Кода получилось несколько больше, чем в оригинале, зато работает как часы. А еще он умеет выдирать название ролика :-). Всю грязную работу выполняют два класса:

  1. httpClient - объектно-риентированная обёртка к функциям библиотеки cURL. Простенький и чертовски удобный класс (мне так кажется, по крайней мере :-).
  2. YouTube - непосредственно парсер кода.

Будем считать, что эти классы лежат в файлах httpclient.php и youtube.php соответственно. Тогда скрипт морды будет выглядеть примерно так:

<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <title>YouTube DirectLink Extractor</title>
</head>
<body>
<h1>YouTube DirectLink Extractor</h1>
<form method="get">
    <label>Enter Youtube URL:</label>
    &lt;input type="text" name="url" value="<?php echo @$_GET['url'] ?>” size=”60″ /?
    <button type=”submit”>Get direct link</button>
</form>
<?php if (isset($_GET['url'])): ?>
<pre>
<?php
include_once ‘httpclient.php’;
include_once ‘youtube.php’;

$client = new httpClient();
$client->setProxy(’proxy.server.ru’, 3128);

$youtube = new YouTube();
$youtube->setHttpClient($client);

/**
 * Execute programme
 *
 */
$result = $youtube->getResult($_GET['url']);

/**
 * Display all results as hash
 *
 */
print_r($result);

/**
 * or output title of url indepently
 *
 */
print ‘URL: ‘ .$youtube->getUrl().’<br />’;
print ‘Title: ‘.$youtube->getTitle().’<br />’;
?>
</pre>
<?php endif; ?>
</body>
</html>

А вот и исходные коды классов: httpclient.php:

class httpClient
{
    /**
     * Свойство, хранящее дескриптор соединения
     *
     * @var  resource
     */
    private $_curl = null;           

    /**
     * Свойство, сохраняющее ответ сервера на запрос
     *
     * @var  stromg
     */
    private $_response = '';           

   /**
    * Конструктор класса
    *
    * @param   void
    * @return  void
    */           

    public function __construct()
    {
        $this->_curl = curl_init();
        $this->_setOption(CURLOPT_RETURNTRANSFER, true);
    }           

    /**
     * Устанавливает параметры дескриптора CURL
     *
     * @param   integer  $option
     * @param   mixed    $value
     * @return  void
     */
    private function _setOption($option, $value)
    {
        curl_setopt($this->_curl, $option, $value);
    }           

    /**
     * Выполняет HTTP-запрос и возвращает ответ сервера
     *
     * @param   string   $url
     * @param   boolean  $header
     * @return  string
     */
    public function get($url, $header = false)
    {
        $this->_setOption(CURLOPT_URL, $url);
        $this->_setOption(CURLOPT_HEADER, $header);
        return curl_exec($this->_curl);
    }           

    /**
     * Устанавливает адрес и порт прокси]
     *
     * @param   string   $host
     * @param   integer  $port
     * @return  void
     */
    public function setProxy($host, $port = 312 8)
    {
        $this->_setOption(CURLOPT_PROXY, $host);
        $this->_setOption(CURLOPT_PROXYPORT, $port);
    }           

    /**
     * Деструктор класса
     *
     * @param   void
     * @return  void
     */
    public function __destruct()
    {
        curl_close($this->_curl);
    }
}

… и youtube.php

class YouTube
{
    /**
     * Свойство, хранящее указатель на объе
     *
     * @var  httpRequest
     */
    private $_httpClient;           

    /**
     * Информация о клипе (по умолчанию пустая ;))
     *
     * @var  httpRequest
     */
    private $_result = array('url' => null, 'title' => null);           

    /**
     * Устанавливает используемый HTTP-клиент
     *
     * @param   httpClient   $client
     * @return  void
     */
    public function setHttpClient(httpClient $client)
    {
        $this->_httpClient = $client;
    }           

    /**
     * Выполняет запрос к серверу YouTube и возвращает хеш-массив с
     * полученным данными
     *
     * @param   string  $url
     * @return  array
     */
    public function getResult($url)
    {
        return $this->_parse($url)->_result;
    }           

    /**
     * Непосредственно парсинг UHTML-страничек и вычленение заголовков с
     * перенаправлениями.
     *
     * @param   string  $url
     * @return  YouTube
     */
    private function _parse($url)
    {
        $code = $this->_httpClient->get($url);           

        if (preg_match('/var fs = window.open( "/(.*?)" + "(.*?)" ,/si', $code, $match)) {
            $code = $this->_httpClient->get('http://youtube.com/'.$match[1]);
            $title = $match[2];           

            if (preg_match(’/”/player2.swf?(.*)”, “player”/si’, $code, $match)) {
                $url = ‘http://youtube.com/get_video.php?’.$match[1]; // работает
                $code = $this->_httpClient->get($url, true);           

                if (preg_match(’/Location:s*?(.*?)n/si’, $code, $match)) {
                    $this->_result['url'] = trim($match[1]);
                    $this->_result['title'] = urldecode($title);
                }
            }
        }           

        return $this;
    }           

    /**
     * Возвращает URL видео
     *
     * @param   void
     * @return  string
     */
    public function getUrl()
    {
        return $this->_result['url'];
    }           

    /**
     * Возвращает название видео
     *
     * @param   void
     * @return  string
     */           

    public function getTitle()
    {
        return $this->_result['title'];
    }
}

Возвращаемая скриптом ссылка является прямой: клик по ней приведет к скачиванию ролика. Название, к сожалению, по дефолту будет «vet_video», но можно ведь и переименовать файл руками, зная название ролика :-). Можно и немного расширить функционал скрипта таким образом, чтобы он автоматом начинал выкачивать файл и предлагал имя, соответствующее названию ролика… Но это уже будет другая история :-)

А пока хотелось бы услышать отзывы, замечания, комментарии. И совет опытных блоггеров: какой лучше всего использовать клиент для постинга? Пользоваться веб-интерфейсом TinyMCE не очень хочется :-)

UPD.: т.к. редакотор не может по-человечески обращаться с кодом и считает своим долгом поубивать лишние (по его мнению, естественно)  бекслеши из регулярных выражений, думаю, что лучше выложить исходники файлов (уберите расширение .txt из имени файла):

index.php
youtube.php
httpclient.php

12 Комментариев

  • [...] php скрипт - скачать видео с youtube [updated] Функциональная и более мастевая версия [...]

  • Красавчик!!!

    На счет клиента, даже не знаю. Раньше Windows Live Writer был более-менее. Но последнии версии у меня почему-то упрямо не желают работать с кирилицей. Попробуй, может то у меня руки сильно кривые.

  • В нете сотни сервисов для скачки видео с Yutube и конвертирования (в avi например)

  • Хм… ну что ж поделаешь, стало быть одним велосипедом в сети стало больше :-)

  • Ссылка на httpclient.php не открывется :(

  • Спасибо, исправлено :)

  • А как насчет расширить функционал, чтобы он предлагал скачать с уже нормальным именем файла?

  • А в чём проблема? :)

  • В том, что я не знаю, как это сделать))

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

    Разбирайтесь, что делает скрипт. Если совсем лениво разбираться, то платите тем, кому не лениво. Сделают в лучшем виде :)

  • Ну, я бы не сказал, что это велосипед, так как веб-сервис это веб-сервис, а скрипт можно внедрить в какое-нибудь свое решение. Что, собственно, я и собираюсь сейчас сделать. Автору спасибо, что сэкономил мне кучу времени. Приступаю к тестированию :)

  • Новый код для скачивания с YouTube:

    http://forum.armdex.com/index.php?act=ST&f=35&t=4657&st=0#entry67341

Ответить