2013-10-05 32 views
7

Youtube'dan yerel dosya sistemine nasıl video indireceğimi anlamaya çalışıyorum. VGet gibi birkaç paket denedim ama çalışmayı başaramıyorum. Herhangi bir yardım çok takdir edilmektedir. Ben vget denedimJava videosunu nasıl indirebilirim?

cevap

10

, https://github.com/axet/vget (https://gitlab.com/axet/vget taşındı) ve iyi çalışıyor. Pom dosyalarından manuel bağımlılıkları kurmak veya indirmek için maven kullanabilirsiniz. bağımlılıklar

public class DirectDownload { 

    public static void main(String[] args) { 
     try { 
      VGet v = new VGet(new URL("http://www.youtube.com/watch?v=fNU4UNPNeWI"), new File("/")); 
      v.download(); 
     } catch (Exception e) { 
      throw new RuntimeException(e); 
     } 
    } 

} 

çek dışarı hazır bir çalışma örneği, kaynaklar dahil edilir,

olarak doğrudan indirme örneği ran JDK6 ile derlenmiş kavanoz

zip dosyası - 1,89KB https://www.wetransfer.com/downloads/465f7ef8c6a76f79e4cbd7c9f38a608c20131005141332/41c09a86ed8eaa6e61f59282eabda2a120131005141332/4ac689

GÜNCELLEME # - yorumlarla

TLDR belirtilen indirirken NPE sorunu;com.github.axet.vget.vhs.YouTubeParser ile ilgili birkaç sorun var gibi görünüyor, bu nedenle, onu yamalamak ve örneği eskiden olduğu gibi çalışmasını sağlamak için müdahaleci olmayan kod ekledi. Bu yüzden, orijinal YoutubeParser sınıfını, sonunda buraya gönderilen biriyle değiştirin.

Ayrıca kavanoz ve gerekli tüm libs ile hazır bir çalışma örneği bulabilirsiniz, kaynaklar kavanozuna dahil edilmiştir (bu süre otomatik olarak kaldırılacaktır (13 Eylül 2014 tarihinde silinecektir) - youtube URL'leri dahil 1,69MB (wetransfer.com görüntüler 1.7MB)

https://www.wetransfer.com/downloads/7b2d9182c9d91577919df3907cfd025620140906080118/a9ded3ba71496d4df9b4d035ac5a1e3920140906080118/6acf46#

A.

KONULAR - kodunda)

zip dosyasını rastlantısal com.github.axet.vget.vhs.YouTubeParser LN229 olarak

  1. değişken qs http elde edilen sorgu dizesi WGet ile idam içermiyor çoğu kez. Bu, sorgu dizesini ayrıştırmaya çalışırken npe'un daha sonra atılmasına neden olur.Sorun 1 URL'ler sonra sig değişken bulunamazsa çözülürse

  2. böylece herhangi bir değer döndürmez Pattern.compile("sig=([^&,]*)") ile ayrıştırma, get_video_info döndü. Bu, videoyu hiç indirmeden sürekli denemelerle sonuçlanır.

B. KARARLARI

  1. kez daha WGet çağrılması durumunda, (yanıtın orijinal formatı ve bilinmeyen wget edepsizlik eden sebebi olarak bu, geçici yamalar vardır) Ortaya çıkan sorgu dizesi boş, WGet.HtmlLoader olmadan iş yapmak gibi görünüyor. Ayrıca, apache httpclient v4 kullanarak basit bir HTTP GET çağırma yaklaşımı sağlanmıştır, bu durumda apache commons-logging.jar'a bir bağımlılık daha vardır.

yüzden biraz ayrıştırma geliştirilmiş, 2.After belli bir yerde imza var gibi görünüyor tepki bakarak ln248

 if (qs == null || qs.trim().length() == 0) { 
      qs = WGet.getHtml(url); 

////below is sample code for simple HTTP GET with httpclient v4 
////if used then apache commons-logging.jar is also required 
//   CloseableHttpClient httpclient = HttpClients.createDefault(); 
//   try { 
//    HttpGet httpget = new HttpGet(get); 
// 
//    System.out.println("Executing request " + httpget.getRequestLine()); 
// 
//    // Create a custom response handler 
//    ResponseHandler<String> responseHandler = new ResponseHandler<String>() { 
// 
//     public String handleResponse(
//       final HttpResponse response) throws ClientProtocolException, IOException { 
//      int status = response.getStatusLine().getStatusCode(); 
//      if (status >= 200 && status < 300) { 
//       HttpEntity entity = response.getEntity(); 
//       return entity != null ? EntityUtils.toString(entity) : null; 
//      } else { 
//       throw new ClientProtocolException("Unexpected response status: " + status); 
//      } 
//     } 
// 
//    }; 
//    String responseBody = httpclient.execute(httpget, responseHandler); 
//    qs = responseBody; 
//   } finally { 
//    httpclient.close(); 
//   } 
     } 

eklendi. Böylece, Pattern.compile("sig=([^&,]*)") modelinin yürütülmesi bir şey döndürmezse, Pattern.compile("signature%3D([^&,%]*)") ile de dener. Bu değişiklik, yöntem extractUrlEncodedVideos'da gerçekleştirilmiştir. Modifiye com.github.axet.vget.vhs.YouTubeParser dosya aşağıdaki gibidir

String sig = null; 
       { 
        Pattern link = Pattern.compile("signature=([^&,]*)"); 
        Matcher linkMatch = link.matcher(urlString); 
        if (linkMatch.find()) { 
         sig = linkMatch.group(1); 
        } else { 
         link = Pattern.compile("signature%3D([^&,%]*)"); 
         linkMatch = link.matcher(urlString); 
         if (linkMatch.find()) { 
          sig = linkMatch.group(1); 
         } 
        } 
       } 

,

package com.github.axet.vget.vhs; 

import java.net.MalformedURLException; 
import java.net.URI; 
import java.net.URISyntaxException; 
import java.net.URL; 
import java.net.URLDecoder; 
import java.util.ArrayList; 
import java.util.HashMap; 
import java.util.List; 
import java.util.Map; 
import java.util.concurrent.atomic.AtomicBoolean; 
import java.util.regex.Matcher; 
import java.util.regex.Pattern; 

import org.apache.commons.lang3.StringEscapeUtils; 
import org.apache.commons.lang3.StringUtils; 
import org.apache.http.NameValuePair; 
import org.apache.http.client.utils.URLEncodedUtils; 

import com.github.axet.vget.info.VGetParser; 
import com.github.axet.vget.info.VideoInfo; 
import com.github.axet.vget.info.VideoInfo.States; 
import com.github.axet.vget.info.VideoInfo.VideoQuality; 
import com.github.axet.wget.WGet; 
import com.github.axet.wget.info.ex.DownloadError; 
import java.io.IOException; 
import org.apache.http.HttpEntity; 
import org.apache.http.HttpResponse; 
import org.apache.http.client.ClientProtocolException; 
import org.apache.http.client.ResponseHandler; 
import org.apache.http.client.methods.HttpGet; 
import org.apache.http.impl.client.CloseableHttpClient; 
import org.apache.http.impl.client.HttpClients; 
import org.apache.http.util.EntityUtils; 

public class YouTubeParser extends VGetParser { 

    public static class VideoUnavailablePlayer extends DownloadError { 

     private static final long serialVersionUID = 10905065542230199L; 

     public VideoUnavailablePlayer() { 
      super("unavailable-player"); 
     } 
    } 

    public static class AgeException extends DownloadError { 

     private static final long serialVersionUID = 1L; 

     public AgeException() { 
      super("Age restriction, account required"); 
     } 
    } 

    public static class PrivateVideoException extends DownloadError { 

     private static final long serialVersionUID = 1L; 

     public PrivateVideoException() { 
      super("Private video"); 
     } 

     public PrivateVideoException(String s) { 
      super(s); 
     } 
    } 

    public static class EmbeddingDisabled extends DownloadError { 

     private static final long serialVersionUID = 1L; 

     public EmbeddingDisabled(String msg) { 
      super(msg); 
     } 
    } 

    public static class VideoDeleted extends DownloadError { 

     private static final long serialVersionUID = 1L; 

     public VideoDeleted(String msg) { 
      super(msg); 
     } 
    } 

    List<VideoDownload> sNextVideoURL = new ArrayList<VideoDownload>(); 

    URL source; 

    public YouTubeParser(URL input) { 
     this.source = input; 
    } 

    public static boolean probe(URL url) { 
     return url.toString().contains("youtube.com"); 
    } 

    void downloadone(VideoInfo info, AtomicBoolean stop, Runnable notify) throws Exception { 
     try { 
      extractEmbedded(info, stop, notify); 
     } catch (EmbeddingDisabled e) { 
      streamCpature(info, stop, notify); 
     } 
    } 

    /** 
    * do not allow to download age restricted videos 
    * 
    * @param info 
    * @param stop 
    * @param notify 
    * @throws Exception 
    */ 
    void streamCpature(final VideoInfo info, final AtomicBoolean stop, final Runnable notify) throws Exception { 
     String html; 
     html = WGet.getHtml(info.getWeb(), new WGet.HtmlLoader() { 
      @Override 
      public void notifyRetry(int delay, Throwable e) { 
       info.setDelay(delay, e); 
       notify.run(); 
      } 

      @Override 
      public void notifyDownloading() { 
       info.setState(States.DOWNLOADING); 
       notify.run(); 
      } 

      @Override 
      public void notifyMoved() { 
       info.setState(States.RETRYING); 
       notify.run(); 
      } 
     }, stop); 
     extractHtmlInfo(info, html, stop, notify); 
     extractIcon(info, html); 
    } 

    /** 
    * Add resolution video for specific youtube link. 
    * 
    * @param url download source url 
    * @throws MalformedURLException 
    */ 
    void addVideo(String itag, String url) throws MalformedURLException { 
     Integer i = Integer.decode(itag); 
     VideoQuality vd = itagMap.get(i); 

     URL u = new URL(url); 

     if (u != null) { 
      sNextVideoURL.add(new VideoDownload(vd, u)); 
     } 
    } 

    // http://en.wikipedia.org/wiki/YouTube#Quality_and_codecs 
    static final Map<Integer, VideoQuality> itagMap = new HashMap<Integer, VideoInfo.VideoQuality>() { 
     private static final long serialVersionUID = -6925194111122038477L; 

     { 
      put(120, VideoQuality.p720); 
      put(102, VideoQuality.p720); 
      put(101, VideoQuality.p360); 
      put(100, VideoQuality.p360); 
      put(85, VideoQuality.p520); 
      put(84, VideoQuality.p720); 
      put(83, VideoQuality.p240); 
      put(82, VideoQuality.p360); 
      put(46, VideoQuality.p1080); 
      put(45, VideoQuality.p720); 
      put(44, VideoQuality.p480); 
      put(43, VideoQuality.p360); 
      put(38, VideoQuality.p3072); 
      put(37, VideoQuality.p1080); 
      put(36, VideoQuality.p240); 
      put(35, VideoQuality.p480); 
      put(34, VideoQuality.p360); 
      put(22, VideoQuality.p720); 
      put(18, VideoQuality.p360); 
      put(17, VideoQuality.p144); 
      put(6, VideoQuality.p270); 
      put(5, VideoQuality.p240); 
     } 
    }; 

    public static String extractId(URL url) { 
     { 
      Pattern u = Pattern.compile("youtube.com/watch?.*v=([^&]*)"); 
      Matcher um = u.matcher(url.toString()); 
      if (um.find()) { 
       return um.group(1); 
      } 
     } 

     { 
      Pattern u = Pattern.compile("youtube.com/v/([^&]*)"); 
      Matcher um = u.matcher(url.toString()); 
      if (um.find()) { 
       return um.group(1); 
      } 
     } 

     return null; 
    } 

    /** 
    * allows to download age restricted videos 
    * 
    * @param info 
    * @param stop 
    * @param notify 
    * @throws Exception 
    */ 
    void extractEmbedded(final VideoInfo info, final AtomicBoolean stop, final Runnable notify) throws Exception { 
     String id = extractId(source); 
     if (id == null) { 
      throw new RuntimeException("unknown url"); 
     } 

     info.setTitle(String.format("http://www.youtube.com/watch?v=%s", id)); 

     String get = String 
       .format("http://www.youtube.com/get_video_info?video_id=%s&el=embedded&ps=default&eurl=", id); 

     URL url = new URL(get); 

     String qs = WGet.getHtml(url, new WGet.HtmlLoader() { 
      @Override 
      public void notifyRetry(int delay, Throwable e) { 
       info.setDelay(delay, e); 
       notify.run(); 
      } 

      @Override 
      public void notifyDownloading() { 
       info.setState(States.DOWNLOADING); 
       notify.run(); 
      } 

      @Override 
      public void notifyMoved() { 
       info.setState(States.RETRYING); 
       notify.run(); 
      } 
     }, stop); 

     if (qs == null || qs.trim().length() == 0) { 
      qs = WGet.getHtml(url); 

////below is sample code for simple HTTP GET with httpclient v4 
////if used then apache commons-logging.jar is also required 
//   CloseableHttpClient httpclient = HttpClients.createDefault(); 
//   try { 
//    HttpGet httpget = new HttpGet(get); 
// 
//    System.out.println("Executing request " + httpget.getRequestLine()); 
// 
//    // Create a custom response handler 
//    ResponseHandler<String> responseHandler = new ResponseHandler<String>() { 
// 
//     public String handleResponse(
//       final HttpResponse response) throws ClientProtocolException, IOException { 
//      int status = response.getStatusLine().getStatusCode(); 
//      if (status >= 200 && status < 300) { 
//       HttpEntity entity = response.getEntity(); 
//       return entity != null ? EntityUtils.toString(entity) : null; 
//      } else { 
//       throw new ClientProtocolException("Unexpected response status: " + status); 
//      } 
//     } 
// 
//    }; 
//    String responseBody = httpclient.execute(httpget, responseHandler); 
//    qs = responseBody; 
//   } finally { 
//    httpclient.close(); 
//   } 
     } 

     Map<String, String> map = getQueryMap(qs); 

     if (map.get("status").equals("fail")) { 
      String r = URLDecoder.decode(map.get("reason"), "UTF-8"); 
      if (map.get("errorcode").equals("150")) { 
       throw new EmbeddingDisabled("error code 150"); 
      } 
      if (map.get("errorcode").equals("100")) { 
       throw new VideoDeleted("error code 100"); 
      } 

      throw new DownloadError(r); 
      // throw new PrivateVideoException(r); 
     } 

     info.setTitle(URLDecoder.decode(map.get("title"), "UTF-8")); 

     // String fmt_list = URLDecoder.decode(map.get("fmt_list"), "UTF-8"); 
     // String[] fmts = fmt_list.split(","); 
     String url_encoded_fmt_stream_map = URLDecoder.decode(map.get("url_encoded_fmt_stream_map"), "UTF-8"); 

     extractUrlEncodedVideos(url_encoded_fmt_stream_map); 

     // 'iurlmaxresæ or 'iurlsd' or 'thumbnail_url' 
     String icon = map.get("thumbnail_url"); 
     icon = URLDecoder.decode(icon, "UTF-8"); 
     info.setIcon(new URL(icon)); 
    } 

    void extractIcon(VideoInfo info, String html) { 
     try { 
      Pattern title = Pattern.compile("itemprop=\"thumbnailUrl\" href=\"(.*)\""); 
      Matcher titleMatch = title.matcher(html); 
      if (titleMatch.find()) { 
       String sline = titleMatch.group(1); 
       sline = StringEscapeUtils.unescapeHtml4(sline); 
       info.setIcon(new URL(sline)); 
      } 
     } catch (RuntimeException e) { 
      throw e; 
     } catch (Exception e) { 
      throw new RuntimeException(e); 
     } 
    } 

    public static Map<String, String> getQueryMap(String qs) { 
     try { 
      qs = qs.trim(); 
      List<NameValuePair> list; 
      list = URLEncodedUtils.parse(new URI(null, null, null, -1, null, qs, null), "UTF-8"); 
      HashMap<String, String> map = new HashMap<String, String>(); 
      for (NameValuePair p : list) { 
       map.put(p.getName(), p.getValue()); 
      } 
      return map; 
     } catch (URISyntaxException e) { 
      throw new RuntimeException(qs, e); 
     } 
    } 

    void extractHtmlInfo(VideoInfo info, String html, AtomicBoolean stop, Runnable notify) throws Exception { 
     { 
      Pattern age = Pattern.compile("(verify_age)"); 
      Matcher ageMatch = age.matcher(html); 
      if (ageMatch.find()) { 
       throw new AgeException(); 
      } 
     } 

     { 
      Pattern age = Pattern.compile("(unavailable-player)"); 
      Matcher ageMatch = age.matcher(html); 
      if (ageMatch.find()) { 
       throw new VideoUnavailablePlayer(); 
      } 
     } 

     { 
      Pattern urlencod = Pattern.compile("\"url_encoded_fmt_stream_map\": \"([^\"]*)\""); 
      Matcher urlencodMatch = urlencod.matcher(html); 
      if (urlencodMatch.find()) { 
       String url_encoded_fmt_stream_map; 
       url_encoded_fmt_stream_map = urlencodMatch.group(1); 

       // normal embedded video, unable to grab age restricted videos 
       Pattern encod = Pattern.compile("url=(.*)"); 
       Matcher encodMatch = encod.matcher(url_encoded_fmt_stream_map); 
       if (encodMatch.find()) { 
        String sline = encodMatch.group(1); 

        extractUrlEncodedVideos(sline); 
       } 

       // stream video 
       Pattern encodStream = Pattern.compile("stream=(.*)"); 
       Matcher encodStreamMatch = encodStream.matcher(url_encoded_fmt_stream_map); 
       if (encodStreamMatch.find()) { 
        String sline = encodStreamMatch.group(1); 

        String[] urlStrings = sline.split("stream="); 

        for (String urlString : urlStrings) { 
         urlString = StringEscapeUtils.unescapeJava(urlString); 

         Pattern link = Pattern.compile("(sparams.*)&itag=(\\d+)&.*&conn=rtmpe(.*),"); 
         Matcher linkMatch = link.matcher(urlString); 
         if (linkMatch.find()) { 

          String sparams = linkMatch.group(1); 
          String itag = linkMatch.group(2); 
          String url = linkMatch.group(3); 

          url = "http" + url + "?" + sparams; 

          url = URLDecoder.decode(url, "UTF-8"); 

          addVideo(itag, url); 
         } 
        } 
       } 
      } 
     } 

     { 
      Pattern title = Pattern.compile("<meta name=\"title\" content=(.*)"); 
      Matcher titleMatch = title.matcher(html); 
      if (titleMatch.find()) { 
       String sline = titleMatch.group(1); 
       String name = sline.replaceFirst("<meta name=\"title\" content=", "").trim(); 
       name = StringUtils.strip(name, "\">"); 
       name = StringEscapeUtils.unescapeHtml4(name); 
       info.setTitle(name); 
      } 
     } 
    } 

    void extractUrlEncodedVideos(String sline) throws Exception { 
     String[] urlStrings = sline.split("url="); 

     for (String urlString : urlStrings) { 
      urlString = StringEscapeUtils.unescapeJava(urlString); 

      // universal request 
      { 
       String url = null; 
       { 
        Pattern link = Pattern.compile("([^&]*)&"); 
        Matcher linkMatch = link.matcher(urlString); 
        if (linkMatch.find()) { 
         url = linkMatch.group(1); 
         url = URLDecoder.decode(url, "UTF-8"); 
        } 
       } 
       String itag = null; 
       { 
        Pattern link = Pattern.compile("itag=(\\d+)"); 
        Matcher linkMatch = link.matcher(urlString); 
        if (linkMatch.find()) { 
         itag = linkMatch.group(1); 
        } 
       } 
       String sig = null; 
       { 
        Pattern link = Pattern.compile("signature=([^&,]*)"); 
        Matcher linkMatch = link.matcher(urlString); 
        if (linkMatch.find()) { 
         sig = linkMatch.group(1); 
        } else { 
         link = Pattern.compile("signature%3D([^&,%]*)"); 
         linkMatch = link.matcher(urlString); 
         if (linkMatch.find()) { 
          sig = linkMatch.group(1); 
         } 
        } 
       } 

       if (url != null && itag != null && sig != null) { 
        try { 
         new URL(url); 

         if (sig != null) { 
          url += "&signature=" + sig; 
         } 

         if (itag != null) { 
          addVideo(itag, url); 
          continue; 
         } 
        } catch (MalformedURLException e) { 
         // ignore bad urls 
        } 
       } 
      } 
     } 
    } 

    @Override 
    public void extract(VideoInfo info, AtomicBoolean stop, Runnable notify) { 
     try { 
      downloadone(info, stop, notify); 

      getVideo(info, sNextVideoURL); 
     } catch (RuntimeException e) { 
      throw e; 
     } catch (Exception e) { 
      throw new RuntimeException(e); 
     } 
    } 

} 
+0

bu ticari amaçla kullanabilir miyim? Demek istediğim, bunun için bir lisans var. –

+0

@Shabarinath Sadece gönderdiğim kodun istediğiniz şekilde kullanıldığından emin olduğumu söyleyebilirim. Vget ve kütüphanelere bağlı olduğu sürece, ticari bir projede kullanılmak üzere serbest olduklarını ancak ticari olarak satılmadıklarını düşünüyorum. Ben vget satıyorum. Ama bütün bunlar sadece spekülasyonlar, lisanslarını en azından vget ve wget'lerden kontrol etmenizi öneririm. – melc

+0

Hazır çalışma örneği çalışmıyor Çalışmıyor – Confuse

İlgili konular