Created
March 5, 2012 08:45
-
-
Save faryne/1977508 to your computer and use it in GitHub Desktop.
利用PHP抓Youtube影片(範例程式)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
使用前請先下載phpQuery, | |
否則你需要自己改寫get_meta_data方法的內容 | |
*/ | |
require_once 'libraries/phpQuery.php'; // 請更改為phpQuery的位置 | |
define('lang_ytdl02', '低品質影片', true); | |
define('lang_ytdl03', '標準品質影片', true); | |
define('lang_ytdl05', '高畫質影片', true); | |
define('lang_ytdl06', '超高畫質影片', true); | |
class ytdl | |
{ | |
// 每一個ID代表一種格式,這裡只列基本的部份。其他還有3gp等格式可用...... | |
private $_format = array( | |
'5' =>array('format'=> 'FLV', 'res'=> '240p', 'desc'=> lang_ytdl02), | |
'18'=>array('format'=> 'MP4', 'res'=> '360p', 'desc'=> lang_ytdl02), | |
'22'=>array('format'=> 'MP4', 'res'=> '720p', 'desc'=> lang_ytdl05), | |
'34'=>array('format'=> 'FLV', 'res'=> '360p', 'desc'=> lang_ytdl02), | |
'35'=>array('format'=> 'FLV', 'res'=> '480p', 'desc'=> lang_ytdl03), | |
'37'=>array('format'=> 'MP4', 'res'=> '1080p', 'desc'=> lang_ytdl06), | |
'38'=>array('format'=> 'MP4', 'res'=> '4k', 'desc'=> lang_ytdl06), | |
'43'=>array('format'=> 'WebM', 'res'=> '360p', 'desc'=> lang_ytdl02), | |
'44'=>array('format'=> 'WebM', 'res'=> '480p', 'desc'=> lang_ytdl03), | |
'45'=>array('format'=> 'WebM', 'res'=> '720p', 'desc'=> lang_ytdl05), | |
'46'=>array('format'=> 'WebM', 'res'=> '1080p', 'desc'=> lang_ytdl06), | |
); | |
private $_ytid; | |
/** | |
建構子 | |
string $ytid: Youtube影片ID | |
string $memory_limit: 因為抓影片時有可能耗盡記憶體,所以此值可以設大一些。不過256M應該是足夠了...... | |
*/ | |
public function __construct ($ytid, $memory_limit = '256M') { | |
$this->_ytid = $ytid; | |
ini_set('memory_limit', $memory_limit); | |
if (!class_exists('phpQuery')) { | |
throw new Exception('No phpQuery class. Please download it at http://code.googe.com/p/phpQuery'); | |
} | |
} | |
/** | |
取得影片標題與各種解析度的影片位址 | |
*/ | |
public function get_meta_data () { | |
$output = array('title'=>'', 'videos'=>array()); | |
// 這裡是抓影片播放頁的資料,如果要減少傳輸量的話,可以用http://www.youtube.com/get_video_info?video_id={ytid},可以少抓很多html廢話,效果也是一樣啦 | |
$url = 'http://www.youtube.com/watch?v='.$this->_ytid; | |
$ch = curl_init($url); | |
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); | |
$content = curl_exec($ch); | |
$info = curl_getinfo($ch); | |
curl_close($ch); | |
if ($info['http_code'] > 299 || $info['http_code'] < 200) { | |
throw new Exception("Cannot fetch video data"); | |
} | |
// 這部份是要抓出影片標題以便掛在影片url用,不過老實說我沒實驗過不加這個會不會怎樣呢? | |
$output['title'] = pq('#eow-title', $pq)->attr('title'); | |
// 接著要來parse影片的位址了 | |
$pattern = '#"url_encoded_fmt_stream_map": "([^"]*)"#i'; | |
preg_match($pattern, $content, $match); | |
if (!isset($match[1])) { | |
throw new Exception('Cannot parse video information'); | |
} | |
$links = explode(',', $match[1]); | |
foreach ($links as $link) { | |
parse_str($link, $d); | |
if (!isset($d['url'])) { | |
continue; | |
} | |
$url = str_replace('\\', '', $d['url']); | |
$url = preg_replace('#(u0026[^&]*)#', '', $url).'&title='.urlencode($output['title']); | |
preg_match('#itag\=([0-9]{1,2})#', $url, $tag); | |
$output['videos'][strval($tag[1])] = $url; | |
} | |
// 傳回結果 | |
return $output; | |
} | |
/** | |
將影片寫入成為檔案 | |
string $url: 影片的uri | |
string $filename: 要存檔的位址 | |
*/ | |
public function get_video ($url, $filename) { | |
// 先把檔案抓下來 | |
$ch = curl_init($url); | |
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); | |
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); | |
$result = curl_exec($ch); | |
$info = curl_getinfo($ch); | |
curl_close($ch); | |
if ($info['http_code'] > 299 || $info['http_code'] < 200) { | |
throw new Exception("HTTP Retrieve failed({$info['http_code']})"); | |
} | |
// 抓下來以後再寫入 | |
$fp = fopen($filename, 'w'); | |
if (!$fp) { | |
throw new Exception("File Open Error"); | |
} | |
fwrite($fp, $result); | |
fclose($fp); | |
return true; | |
} | |
} | |
try { | |
$ytid = "NvB5IhJ-m40"; | |
$ytdler = new ytdl($ytid); | |
$info = $ytdler->get_meta_data(); | |
if (!isset($info['videos']['5'])) { | |
throw new Exception("Cannot get low resolution video"; | |
} | |
// 抓影片啦 | |
$filename = $ytid.".mp4"; | |
$ytdler->get_video($info['videos']['5'], $filename); | |
} catch (Exception $e) { | |
echo 'Error: '.$e->getMessage()."\n"; | |
die(); | |
} | |
?> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment