优酷视频真实地址最新解析方法 2011.11.08有效

最近掌上优酷的老用户说不能播放,那个是用网上公开的API和KEY写的,估计是优酷把那个KEY给封了(优酷没土豆大方,KEY不是普通人能申请得到的).因为优酷之前给各大市场发律师信,要求封杀掌上优酷,所以这里只做技术研究,掌上优酷还是不会再更新. 下面的代码是参考http://3shi.net/analyze-youku-video-address/ 写的,没有采用优酷的API,但是最近优酷又稍稍改了,原文的有些部分已经不适用,取到的地址不能再播放. 这段代码会优先取MP4格式的视频,没有MP4格式才取FLV格式.需要使用org.json

package com.test;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

public class Main
{

    public static void main(String[] args) throws Exception
    {
        String id="XMzE3OTQ0Nzk2";
        String s = Common.getHtml("http://v.youku.com/player/getPlayList/VideoIDS/"+id);
        JSONObject jsobj = new JSONObject(s);
        JSONArray jsonarr = jsobj.getJSONArray("data");
        JSONObject obj1 = jsonarr.getJSONObject(0);
        double seed = obj1.getDouble("seed");
        JSONObject obj2 = obj1.getJSONObject("streamfileids");
        String mp4id = null;
        String flvid = null;
        String format = null;
        try
        {
            mp4id = obj2.getString("mp4");
            format = "mp4";
        } catch (JSONException e)
        {
            System.out.println("没有MP4格式");
            try
            {
                flvid = obj2.getString("flv");
                format = "flv";
            } catch (JSONException e1)
            {
                System.out.println("没有FLV格式");
                return;
            }
        }

        String realfileid = null;
        if (format.equals("mp4"))
        {
            realfileid = getFileID(mp4id, seed);
        } else
        {
            realfileid = getFileID(flvid, seed);
        }
        String idLeft = realfileid.substring(0, 8);
        String idRight = realfileid.substring(10);

        String sid = genSid();
        JSONObject obj3 = obj1.getJSONObject("segs");
        JSONArray mp4arr = obj3.getJSONArray(format);
        for (int i = 0; i < mp4arr.length(); i++)
        {
            JSONObject o = mp4arr.getJSONObject(i);
            String k = o.getString("k");
            String url = "http://f.youku.com/player/getFlvPath/sid/" + sid + "_" + String.format("%1$02X", i) + "/st/" + format
                    + "/fileid/" + idLeft + String.format("%1$02X", i) + idRight + "?K=" + k;
            System.out.println(url);
        }

    }

    private static String getFileID(String fileid, double seed)
    {
        String mixed = getFileIDMixString(seed);
        String[] ids = fileid.split("\\*");
        StringBuilder realId = new StringBuilder();
        int idx;
        for (int i = 0; i < ids.length; i++)
        {
            idx = Integer.parseInt(ids[i]);
            realId.append(mixed.charAt(idx));
        }
        return realId.toString();
    }

    public static String genSid()
    {
        int i1 = (int) (1000 + Math.floor(Math.random() * 999));
        int i2 = (int) (1000 + Math.floor(Math.random() * 9000));
        return System.currentTimeMillis() + "" + i1 + "" + i2;
    }

    private static String getFileIDMixString(double seed)
    {
        StringBuilder mixed = new StringBuilder();
        StringBuilder source = new StringBuilder("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/\\:._-1234567890");
        int index, len = source.length();
        for (int i = 0; i < len; ++i)
        {
            seed = (seed * 211 + 30031) % 65536;
            index = (int) Math.floor(seed / 65536 * source.length());
            mixed.append(source.charAt(index));
            source.deleteCharAt(index);
        }
        return mixed.toString();
    }

}