您的位置:首页 > 理论基础 > 计算机网络

网络直播电视之寻找直播地址

2013-01-31 17:40 288 查看
这种方式也不知道能坚持多长时间,暂时是没有什么问题。方法如下:

访问http://trailers.apple.com/appletv/index.xml

可以看到'http://atv.jianguoke.com/appletv/tv/tv.xml');"onPlay="">

打开http://atv.jianguoke.com/appletv/tv/tv.xml

可以看到直播电视的分类 打开央视直播

http://atv.jianguoke.com/appletv/tv/list_1.xml

可以看到cctv1

http://atv.jianguoke.com/appletv/tv/live_1_1.xml

继续打开可以得到新版的cctv1地址

http://tvhd.ak.live.cntv.cn/cache/1_/seg0/index.m3u8

通过这种方法便可以拿到直播地址了。如果拿人工的方式获取相关数据,毫无疑问累死人不偿命的。我会将有关这些XML解析的方法和函数进行公布,希望给大家提供一定的帮助。

接上文,上文中提到获取网络直播电视地址的方法,但是大量信息需要人工的方式进行处理,过于麻烦。所以本文针对三级的XML解析和下载工作进行处理。

技术点:1、利用tinyXML完成XML的解析工作 tinyxml下载

2、利用libcurl完成xml的下载工作 libcurl下载

公用下载函数:

[cpp] view
plaincopy

// 下载相关的XML

static size_t write_data(void *buffer, size_t size, size_t nmemb, void *userp)

{

size_t nsize=size*nmemb;

//…在这里保存数据

string *strHtml=(string*)userp;

strHtml->append((char*)buffer,nsize);

return nsize;

}

bool downloadXml(const char* fileUrl, string& xmlStr)

{

if ("" == fileUrl)

{

dxreport("downloadXml: fileUrl is empty ...");

return false;

}

xmlStr = ""; // 清空缓存XML

CURL* m_curl = curl_easy_init();

if (NULL == m_curl)

{

dxreport("downloadXml: create curl fail ...");

return false;

}

string* str = new string();

curl_easy_reset(m_curl); //主要是在重复调用GET/POST时,清空curl中的设置

curl_easy_setopt(m_curl, CURLOPT_URL, fileUrl);

curl_easy_setopt(m_curl, CURLOPT_FOLLOWLOCATION, 1);

curl_easy_setopt(m_curl, CURLOPT_WRITEDATA,(void *)str);

curl_easy_setopt(m_curl, CURLOPT_WRITEFUNCTION, write_data);

CURLcode res = curl_easy_perform(m_curl);

curl_easy_cleanup(m_curl);

if (res != CURLE_OK || str->length() == 0)

{

dxreport("downloadXml: download xml fail! url = %s", fileUrl);

cout << fileUrl << endl;

return false;

}

xmlStr = *str;

return true;

}

解析第一级XML:

[html] view
plaincopy

<?xml version="1.0" encoding="UTF-8"?>

<atv>

<body>

<listScrollerSplit id="com.sample.list-scroller-split">

<header>

<simpleHeader>

<title>电视直播</title>

</simpleHeader>

</header>

<menu>

<sections>

<menuSection>

<header>

<textDivider alignment="left">

<title>类别选择</title>

</textDivider>

</header>

<items>

<oneLineMenuItem id="list_1">

<label>央视直播</label>

<preview>

<link>http://atv.jianguoke.com/appletv/tv/list_1.xml</link>

</preview>

</oneLineMenuItem>

</items>

</menuSection>

</sections>

</menu>

</listScrollerSplit>

</body>

</atv>

样例XML如上所示,现在我们开始解析工作。

[cpp] view
plaincopy

// 解析第一级XML

bool parseFristXml(const char* fileName, list<CHANNEL_INFO>& listChannel)

{

string strXml = "";

if (false == downloadXml(fileName, strXml))

{

return false;

}

TiXmlDocument* document = new TiXmlDocument();

if (false == document->Parse(strXml.c_str()))

{

return false;

}

/*TiXmlDeclaration *decl;

decl = document->FirstChild()->ToDeclaration();*/

// 查找到根部

TiXmlElement* rootElement = document->RootElement();

TiXmlElement* keyBody = rootElement->FirstChildElement();

TiXmlElement* keyListScrollerSplit = keyBody->FirstChildElement();

TiXmlElement* keyHeadFrist = keyListScrollerSplit->FirstChildElement();

TiXmlElement* keyMenu = keyHeadFrist->NextSiblingElement();

if (keyMenu == NULL)

{

return false;

}

// 进入到menu中

TiXmlElement* keySections = keyMenu->FirstChildElement();

TiXmlElement* keySectionsMenu = keySections->FirstChildElement();

TiXmlElement* keySectionsHeaderMenu = keySectionsMenu->FirstChildElement();

TiXmlElement* keySectionsItems = keySectionsHeaderMenu->NextSiblingElement(); // 发现解析头部

TiXmlElement* item = keySectionsItems->FirstChildElement(); // 取得第一个标签

while (item)

{

CHANNEL_INFO info;

TiXmlElement* oneLineMenuItem = item->FirstChildElement(); // 获取lable的内容

info.name = changeTxtEncoding(oneLineMenuItem->GetText());

oneLineMenuItem = oneLineMenuItem->NextSiblingElement()->FirstChildElement();

info.fileUrl = oneLineMenuItem->GetText();

listChannel.push_back(info); // 存储数据

item = item->NextSiblingElement(); // 切到下个标记

}

return true;

}

tinyXML函数的具体使用在这里就不累赘了,针对TinyXML解析方法可参见博客的其他相关内容。

解析第二级XML:

[html] view
plaincopy

<?xml version="1.0" encoding="UTF-8"?>

<atv>

<head>

<script src="http://atv.jianguoke.com/appletv/video.js"/>

</head>

<body>

<preview>

<scrollerPreview id="com.sample.scrollerPreview">

<items>

<grid id="grid_1" columnCount="5">

<items>

<sixteenByNinePoster id="type1_1" alwaysShowTitles="true" accessibilityLabel="" onHoldSelect="savevideofav('http://atv.jianguoke.com/appletv/tv/live_1_1.xml', 'http://atv.jianguoke.com/appletv/tv/img/m_cctv1.png', 'CCTV-1 综合', '5')" onSelect="playvideo('http://atv.jianguoke.com/appletv/tv/live_1_1.xml', 'http://atv.jianguoke.com/appletv/tv/live_1_1.xml', 'CCTV-1 综合', '5')" onPlay="playvideo('http://atv.jianguoke.com/appletv/tv/live_1_1.xml', 'http://atv.jianguoke.com/appletv/tv/live_1_1.xml', 'CCTV-1 综合', '5')">

<title>CCTV-1 综合</title>

<image>http://atv.jianguoke.com/appletv/tv/img/m_cctv1.png</image>

<defaultImage>resource://Poster.png</defaultImage>

</sixteenByNinePoster>

<sixteenByNinePoster id="type1_2" alwaysShowTitles="true" accessibilityLabel="" onHoldSelect="savevideofav('http://atv.jianguoke.com/appletv/tv/live_1_2.xml', 'http://atv.jianguoke.com/appletv/tv/img/m_cctv2.png', 'CCTV-2 财经', '5')" onSelect="playvideo('http://atv.jianguoke.com/appletv/tv/live_1_2.xml', 'http://atv.jianguoke.com/appletv/tv/live_1_2.xml', 'CCTV-2 财经', '5')" onPlay="playvideo('http://atv.jianguoke.com/appletv/tv/live_1_2.xml', 'http://atv.jianguoke.com/appletv/tv/live_1_2.xml', 'CCTV-2 财经', '5')">

<title>CCTV-2 财经</title>

<image>http://atv.jianguoke.com/appletv/tv/img/m_cctv2.png</image>

<defaultImage>resource://Poster.png</defaultImage>

</sixteenByNinePoster>

</items>

</grid>

</items>

</scrollerPreview>

</preview>

</body>

</atv>

处理函数为:

[cpp] view
plaincopy

// 解析第二级XML

bool parseSecondXml(list<CHANNEL_INFO> fristXmlChannel, list<CHANNEL_INFO>& secondXmlChannel)

{

int len = fristXmlChannel.size();

if (len == 0)

{

dxreport("parseSecondXml: get fristXmlChannel is empty!");

return false;

}

for (int i = 0; i < len; i++)

{

CHANNEL_INFO info;

list<CHANNEL_INFO>::iterator iter = fristXmlChannel.begin();

info = (*iter);

fristXmlChannel.pop_front(); // 清除头部的数据

string strXml = "";

if (false == downloadXml(info.fileUrl.c_str(), strXml))

{

continue;

}

// 进行二级解析XML

TiXmlDocument* document = new TiXmlDocument();

if (false == document->Parse(strXml.c_str()))

{

return false;

}

TiXmlElement* element = document->RootElement();

element = element->FirstChildElement();

element = element->NextSiblingElement(); // body

for (int i = 0; i < 6; i++)

{

element = element->FirstChildElement();

}

// 获取三级XML下载地址

while (element)

{

TiXmlAttribute* attribute = element->FirstAttribute();

while (attribute)

{

string keyName = attribute->Name();

if (keyName == "onPlay")

{

// 获取到的内容如下格式:

//"playvideo('http://atv.jianguoke.com/appletv/tv/live_1_1.xml', 'http://atv.jianguoke.com/appletv/tv/live_1_1.xml', 'CCTV-1 综合', '5')"

string strContent = attribute->Value();

// 解析字符串

int len = strContent.length();

string keyStr[4] = {"", "", "", ""};

string str = "";

int keyNum = 0;

for (int i = 0; i < len; i ++)

{

if (strContent[i] == '\'')

{

if (strContent[i+1] == ',')

{

keyStr[keyNum] = str;

keyNum ++;

}

str = "";

continue;

}

str += strContent[i];

}

// 存储数据

CHANNEL_INFO newInfo;

newInfo.fileUrl = keyStr[0];

newInfo.name = changeTxtEncoding(keyStr[2].c_str());

secondXmlChannel.push_back(newInfo);

}

attribute = attribute->Next();

}

element = element->NextSiblingElement();

}

}

return true;

}

解析第三级XML:

[html] view
plaincopy

<?xml version="1.0" encoding="UTF-8"?>

<atv>

<body>

<videoPlayer id="com.sample.video-player">

<httpFileVideoAsset id="live_3_5">

<mediaURL>http://182.140.144.32:8080/playlist/37.m3u8?key=rkH0PG-pfffEkcMUDSZoEwbswucCuObIj1fYeg..</mediaURL>

<title/>

<description/>

<image/>

</httpFileVideoAsset>

</videoPlayer>

</body>

</atv>

解析函数:

[cpp] view
plaincopy

// 解析最后一级XML

bool parseEndXml(list<CHANNEL_INFO> secondXmlChannel, list<CHANNEL_INFO>& endXmlChannel)

{

int len = secondXmlChannel.size();

if (len == 0)

{

dxreport("parseSecondXml: get fristXmlChannel is empty!");

return false;

}

for (int i = 0; i < len; i++)

{

CHANNEL_INFO info;

list<CHANNEL_INFO>::iterator iter = secondXmlChannel.begin();

info = (*iter);

secondXmlChannel.pop_front(); // 清除头部的数据

string strXml = "";

if (false == downloadXml(info.fileUrl.c_str(), strXml))

{

continue;

}

// 进行三级级解析XML

TiXmlDocument* document = new TiXmlDocument();

if (false == document->Parse(strXml.c_str()))

{

return false;

}

TiXmlElement* element = document->RootElement();

for (int i = 0; i < 4; i++)

{

element = element->FirstChildElement();

}

CHANNEL_INFO newInfo;

newInfo.fileUrl = element->GetText();

newInfo.name = info.name;

endXmlChannel.push_back(newInfo);

cout << newInfo.name << ":" << newInfo.fileUrl << endl;

}

return true;

}

以上就是相关处理内容。望给各位有所帮助 ....
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: