首页 新闻 论坛 群组 Blog 文档 下载 读书 Tag 网摘 搜索 开源 FAQ 第二书店 博文视点 程序员
频道: 研发 数据库 中间件 信息化 视频 .NET Java 游戏 移动 服务: 人才 外包 培训
    图书品种:235680
       
热门搜索: ASP.NET Ajax Spring Hibernate Java

12.5  电视节目时间表

电视节目时间表是一项非常实用的信息,本例的目标就是向用户提供电视节目时间表的在线查询服务。电视节目时间表是一种需要经常更新的信息,这里的最终数据源是TVMAO网站提供的。

12.5.1  概述

打开页面http://www.tvmao.com/ext/demo_tv.html,可以看到如图12.5所示的页面。这个界面就是TVMAO网站向其他站点提供的查询调用界面。如果作为一个查询项目,这个界面占用的空间就有点太大了。并且,查询项目一般更倾向于使用文本框或者下拉框进行输入。本例的目标就是把这个查询界面改造成如图12.6所示。

图12.5  TVMAO的数据调用演示界面图

图12.6  改良后的查询界面效果图

图12.7所示是单击【查询】按钮,查询结果界面。

图12.7  得到查询结果后的效果图

仔细观察上面的几个运行效果图,可以发现,与电视节目时间表查询相关的数据有两类。一类是相对固定的数据,如各省的数据、电台数据、电台各频道的数据。这些数据在短时间内基本没什么变化,为了使用方便,最好能把它收集到自己的服务器数据库中。另一类属于及时性的数据,数据内容和时间有密切关系,如各电台频道的电视节目时间表。这些数据经常更新,无法在本地固定存储,只能随时从TVMAO获得。电视节目时间表查询项目可以分为两部分:固定数据的获取和在线查询。

12.5.2  固定数据的获取

通过以上的分析可以发现,固定数据可以在一个表中进行存储。新建一个SQL数据库,在数据库中添加一个表,命名为TV。TV表用来记录每个电视台频道的数据,包括所属省市、所属电台以及频道的简写(也是TVMAO上本频道电视节目的url)。表TV的详细字段设计如表12-2所示。

表12-2                                                       表TV的字段设计

字  段  名

字 段 类 型

字 段 说 明

Id

int

关键字,电视台的标志

Prov

Nvarcahar(200)

省市

Classname

Nvarcahar(300)

大类的名称

Channel

Nvarcahar(300)

电视台名称

url

Nvarchar(500)

频道的简写

如何获取这些数据信息呢?当然只能从TVMAO的演示界面中获取。查看如图12.5所示效果图的源文件,其包括如下代码:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

<html>

<head>

<title> TVMAO 节目表风格定制示例 </title>

<meta name="Author" content="">

<meta name="Keywords" content="">

<meta name="Description" content="">

<script language="JavaScript">

     var W_Height=530;//整个窗口的高度

     var W_Width=580;//整个窗口的宽度

     var Top_Height=60;//顶部导航的高度

     var Left_Width=200;//左侧频道列表的宽度

   var Area_ID="FJTV";//设置缺省的地区ID

</script>

</head>

<body>

<script type="text/JavaScript" src="http://www.tvmao.com/ext/tvmao.js"></script>

</body>

</html>

这个页面文件的头部定义了一些变量,而页面主体是http://www.tvmao.com/ext/tvmao.js这个脚本。下载这个脚本,发现脚本文件中有如下代码:

var DEF_W_HEIGHT="700";

DEF_W_WIDTH="600";

DEF_TOP_HEIGHT="60";

DEF_LEFT_WIDTH="200";

DEF_MAIN_WIDTH="400";

try{void (W_Height);void (W_Width);void (Top_Height);void (Left_Width);void (Main_Width);}catch(e){

W_Height=DEF_W_HEIGHT;W_Width=DEF_W_WIDTH;Top_Height=DEF_TOP_HEIGHT;Left_Width= DEF_LEFT_WIDTH;Main_Width=DEF_MAIN_WIDTH;}

if(isNaN(W_Height))

        {W_Height=DEF_W_HEIGHT;}

if(isNaN(W_Width))

       {W_Width=DEF_W_WIDTH;}if(isNaN(Top_Height)) {Top_Height=DEF_TOP_HEIGHT;}

if(isNaN(Left_Width))

       {Left_Width=DEF_LEFT_WIDTH;}if(isNaN(Main_Width)) {Main_Width=DEF_MAIN_WIDTH;}

var Main_Width=W_Width-Left_Width;              //主窗口节目表的宽度

//custom radio

var DEF_AREA_ID="CCTV";

try{void (Area_ID)}catch(e){Area_ID=DEF_AREA_ID;}

var st = window.location.protocol + "//" + window.location.hostname;

var s = '<table border=0 height="'+W_Height+'" width="'+W_Width+'" cellspacing=0 cellpadding=0><tr>';

s += '<td colspan=2 height='+Top_Height+'><iframe width="100%" style="margin-top: 0px;margin-left:0px;padding-left:2px;" height="100%" marginheight=0 frameborder=0 scrolling=no id=a_frame name=a_frame src="http://www.tvmao.com/ext/a.html?st='+st+'"> </iframe></td>';

s += '</tr><tr>';

s += '<td width='+Left_Width+' valign=top><iframe width="99%" height="100%" margin height=0 frameborder=0 scrolling=auto id=r_frame name=r_frame src="http://www.tvmao. com/ext/r.jsp?a='+Area_ID+'&st='+st+'"></iframe></td>';

s += '<td width='+Main_Width+' valign=top><iframe width="100%" height="100%" margin height=0 frameborder=0 scrolling=auto id=p_frame name=main_frame src="http://www. tvmao.com/ext/show_tv.jsp?a='+Area_ID+'&st='+st+'"></iframe></td>';

s += '</tr></table>';

document.write(s);

由上面的代码可以看出,TVMAO的演示界面包括了3个页面:http://www.tvmao.com/ ext/a.html用来显示所有省的信息、http://www.tvmao.com/ext/show_tv.jsp用来显示某个电台频道的节目时间表、http://www.tvmao.com/ext/r.jsp用来显示各省的所有电台和电台频道,这正是系统所需要的数据。以香港为例,打开http://www.tvmao.com/ext/r.jsp?a=HK这个页面,可以看到如下代码:

<html>

<head>

<meta http-equiv="Content-Type" content="text/html; charset=gb2312">

<title></title>

<script type="text/javascript" src="qqmenu.js"></script>

<link href="http://www.tvmao.com/default_tv.css" rel="stylesheet" type="text/css">

<link id="custom_tvmao_tv" href="" rel="stylesheet" type="text/css">

<script type="text/javascript" src="http://www.tvmao.com/ext/chg_css.js"></script>

<BASE  target="main_frame">

</head>

<body>

<table border="0" cellspacing="0" cellpadding="0" id="menuTab">

  <tr>

    <td id="menuTD">

     <script type="text/javascript">

     p = new qqMenu('p');

     p.add(0,-1,'TVB','','menu');

p.add(1,0,'TVB翡翠台','http://www.tvmao.com/ext/show_tv.jsp?c=TVB1');

p.add(2,0,'TVB Pearl','http://www.tvmao.com/ext/show_tv.jsp?c=TVB2');

p.add(3,0,'TVB无线剧集台','http://www.tvmao.com/ext/show_tv.jsp?c=TVB3');

p.add(4,0,'TVB无线经典台','http://www.tvmao.com/ext/show_tv.jsp?c=TVB4');

p.add(5,0,'TVB无线音乐台','http://www.tvmao.com/ext/show_tv.jsp?c=TVB5');

p.add(6,0,'TVB无线新闻台','http://www.tvmao.com/ext/show_tv.jsp?c=TVB6');

p.add(7,0,'TVB无线健康台','http://www.tvmao.com/ext/show_tv.jsp?c=TVB7');

p.add(8,0,'TVB无线儿童台','http://www.tvmao.com/ext/show_tv.jsp?c=TVB8');

p.add(9,0,'TVB星河频道','http://www.tvmao.com/ext/show_tv.jsp?c=TVB9');

p.add(10,0,'TVB8','http://www.tvmao.com/ext/show_tv.jsp?c=TVB10');

p.add(11,-1,'华娱卫视','','menu');

p.add(12,11,'华娱卫视','http://www.tvmao.com/ext/show_tv.jsp?c=HUAYU1');

p.add(13,-1,'星空卫视','','menu');

p.add(14,13,'星空卫视','http://www.tvmao.com/ext/show_tv.jsp?c=XINGKONG1');

p.add(15,13,'星空卫视音乐频道','http://www.tvmao.com/ext/show_tv.jsp?c=STARTV1');

p.add(16,13,'星空卫视国际电影频道','http://www.tvmao.com/ext/show_tv.jsp?c=STARTV2');

p.add(17,13,'国家地理频道','http://www.tvmao.com/ext/show_tv.jsp?c=STARTV3');

p.add(18,13,'星空卫视英文节目表','http://www.tvmao.com/ext/show_tv.jsp?c=STARTV4');

p.add(19,-1,'凤凰卫视','','menu');

p.add(20,19,'凤凰卫视中文台','http://www.tvmao.com/ext/show_tv.jsp?c=PHOENIX1');

p.add(21,19,'凤凰卫视资讯台','http://www.tvmao.com/ext/show_tv.jsp?c=PHOENIX2');

p.add(22,19,'凤凰卫视欧洲台','http://www.tvmao.com/ext/show_tv.jsp?c=PHOENIX3');

p.add(23,19,'凤凰卫视美州台','http://www.tvmao.com/ext/show_tv.jsp?c=PHOENIX4');

p.add(24,19,'凤凰卫视电影台','http://www.tvmao.com/ext/show_tv.jsp?c=PHOENIX5');

p.add(25,-1,'香港亚洲电视','','menu');

p.add(26,25,'香港亚州电视本港台','http://www.tvmao.com/ext/show_tv.jsp?c=HKATV1');

p.add(27,25,'香港亚州电视国际台','http://www.tvmao.com/ext/show_tv.jsp?c=HKATV2');

p.add(28,25,'香港亚州电视美洲版东岸','http://www.tvmao.com/ext/show_tv.jsp?c=HKATV3');

p.add(29,25,'香港亚州电视美洲版西岸','http://www.tvmao.com/ext/show_tv.jsp?c=HKATV4');

p.add(30,-1,'阳光卫视','','menu');

p.add(31,30,'阳光卫视','http://www.tvmao.com/ext/show_tv.jsp?c=CHINASUN1');

p.add(32,-1,'香港美亚影视台','','menu');

p.add(33,32,'香港美亚影视台','http://www.tvmao.com/ext/show_tv.jsp?c=MATV1');

p.add(34,32,'香港电影台','http://www.tvmao.com/ext/show_tv.jsp?c=MATV2');

p.add(35,32,'香港美亚电视剧台','http://www.tvmao.com/ext/show_tv.jsp?c=MATV3');

p.add(36,32,'美亚电影台(香港)','http://www.tvmao.com/ext/show_tv.jsp?c=MATV4');

p.add(37,32,'美亚电影台(亚洲)','http://www.tvmao.com/ext/show_tv.jsp?c=MATV5');

p.add(38,-1,'东风卫视','','menu');

p.add(39,38,'东风卫视','http://www.tvmao.com/ext/show_tv.jsp?c=AZIOTV1');

p.add(40,-1,'天映频道','','menu');

p.add(41,40,'天映电影频道','http://www.tvmao.com/ext/show_tv.jsp?c=CELETV1');

document.write(p);

     //p.itemStatus(1,0);

     p.o(0);

     </script>  </td>

 </tr>

</table>

</body>

</html>

系统所需要的固定数据全在这个页面。用Thief类获取这个页面,然后再用正则表达式获取每条记录,插入数据库即可。限于篇幅,具体过程读者可自己实现。

12.5.3  节目查询页面Tv.aspx

在线查询的界面比较简单,其设计时期效果如图12.8所示。

整个界面主要由3个下拉框组成,分别用来显示省份、电视台和频道。其中红色字体部分是异步加载数据时的信息提示区,最底部的黑色文字区域是用来显示查询结果的。Tv.aspx的详细实现代码如下:

图12.8  查询界面的设计时期图

<%@ Page Language="C#" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http: //www. w3. org/ TR/xhtml1 /DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">

<head runat="server">

    <title>电视节目查询</title>

    <script type="text/javascript" src="xmlhttp.js"></script>

</head>

<body>

    <form id="form1" runat="server">

         <div align="center">

              <h2>

                  电视节目查询</h2>

              <table border="0" cellpadding="0" cellspacing="0" width="500px">

                   <tr>

                        <td align="center" height="30">

                             省份:

                             <select id="tvprov" onchange="gettvarray(this);changestv
                                  (1,true);">

                                  <option value="安徽">安徽</option>

                                  <option value="澳门">澳门</option>

                                  <option value="北京">北京</option>

                                  <option value="福建">福建</option>

                                  <option value="甘肃">甘肃</option>

                                  <option value="广东">广东</option>

                                  <option value="广西">广西</option>

                                  <option value="贵州">贵州</option>

                                  <option value="海南">海南</option>

                                  <option value="海外">海外</option>

                                  <option value="河北">河北</option>

                                  <option value="河南">河南</option>

                                  <option value="黑龙江">黑龙江</option>

                                  <option value="湖北">湖北</option>

                                  <option value="湖南">湖南</option>

                                  <option value="吉林">吉林</option>

                                  <option value="江苏">江苏</option>

                                  <option value="江西">江西</option>

                                  <option value="辽宁">辽宁</option>

                                  <option value="内蒙古">内蒙古</option>

                                  <option value="宁夏">宁夏</option>

                                  <option value="山东">山东</option>

                                  <option value="山西">山西</option>

                                  <option value="陕西">陕西</option>

                                  <option value="上海">上海</option>

                                  <option value="四川">四川</option>

                                  <option value="台湾">台湾</option>

                                  <option value="天津">天津</option>

                                  <option value="香港">香港</option>

                                  <option value="新疆">新疆</option>

                                  <option value="云南">云南</option>

                                  <option value="浙江">浙江</option>

                                  <option selected="selected" value="中央台">中央台
                                       </option>

                                  <option value="重庆">重庆</option>

                             </select>

                             电视台:<select id="tv_ct" onchange="changestv(1,true)"
                                  style="width: 95px"></select>

                        </td>

                   </tr>

                   <tr>

                         <td height="30">

                        频道列表:<select id="tv_s3" onchange="gettvset()" style="width: 214px"></select></td>

                   </tr>

                   <tr>

                        <td align="center" height="25">

                             <input onclick="gettvset();" type="button" value="查 询" />

                        </td>

                  </tr>

                  <tr>

                       <td style="text-align: left">

                             <div style="display: none; color: Red; text-align: center" id="loadingflag">

                                  正在查找您选择的电台的节目表</div>

                             <span id="resulttv" style="text-align: left">选择省份,频道列表,电视台即可查询相应电台近一周的节目。</span>

                        </td>

                  </tr>

             </table>

             <script type="text/javascript" src="tv.js"></script>

             <br />            &nbsp;

             <br />

        </div>

    </form>

</body>

</html>

12.5.4  脚本文件Tv.js

与Tv.aspx页面文件相关的脚本文件是Tv.js。它负责向服务器发送异步请求,然后处理服务器的返回结果。在Tv.js中,定义了一个数组tvarray,用来存储各电视台频道。严格来说,tvarray是一个数组的数组,它里面的每个元素都是一个4维数组,分别表示省、电台、频道和频道编号。Tv.aspx页面初始化时,首先获取一个省的电台频道信息,存储在tvarray数组中。如果选择了其他省,则首先遍历tvarray数组,如果存在这个省的数据,直接取出。若不存在,则重新从服务器异步获取,把获取数据存储在数组中。

至于对某个电视频道节目时间表的查询,则是异步请求Tv.ashx,然后把返回结果合理显示。本章中对XMLHTTP的封装,仍采用的是前面章节中的XMLHTTP.js这个脚本。Tv.js的实现代码如下:

//和电视节目预告相关的脚本

var tvarray=new Array();//电视台频道数组

//更改频道下拉框数据或更改电台下拉框数据;index:省下拉框的选择项;isurl:;

//flag:为非空表示更改电台列表数据,为空表示更改频道列表数据

function changestv(index,isurl,flag)

{

var obj=$("tv_ct");                                 //电台下拉框

var obj2=$("tv_s3");                                    //频道下拉框

if(flag)                                                //是要求更改频道下拉框的数据

     {

       obj=$("tvprov");

       obj2=$("tv_ct");

     }

obj2.options.length=0;                              //清空频道下拉框的数据

for(var i=0;i<tvarray.length;i++)                       //遍历频道数组

  {

      if(tvarray[i][index]==obj.value)                    //属于本电台

      {

             var tvx;

             if(isurl)                                  //有编码

             {

                    tvx=new Option(tvarray[i][index+1],tvarray[i][3]);

             }

             else

             {

                    tvx=new Option(tvarray[i][index+1],tvarray[i][index+1]);

             }

             var isexists=false;                        //此频道是否已经添加上

             //遍历频道下拉框,查找是否已经添加了这个频道

             for(var x=0;x<obj2.options.length;x++)

             {

                   if(obj2.options[x].value==tvarray[i][index+1])

                   isexists=true;

             }

             if(!isexists)

             obj2.options[obj2.length]=tvx;             //在频道下拉框中添加一个选项

      }

  }

}

//从服务器得到某省电台列表后的回调函数

function rectvprov(req,data)

{

var xml=req.responseXML;                                //获得数据

if(xml==null)return;

var root=xml.documentElement;

if(root)                                                //如果存在

{

       //遍历每条数据,添加到频道数组中

       for(var i=0;i<root.childNodes.length;i++)

       {

             var tvp_1=root.childNodes[i].selectSingleNode("prov").text;

                                                    //获取省信息

             var tvc_1=root.childNodes[i].selectSingleNode("classname").text;

                                                    //获取电台信息

             var tvch_1=root.childNodes[i].selectSingleNode("channel").text;

                                                    //获取频道信息

             var tvu_1=root.childNodes[i].selectSingleNode("url").text;  //频道编号

             tvarray[tvarray.length]=new Array(tvp_1,tvc_1,tvch_1,tvu_1);//添加信息

       }

}

changestv(0,false,1);                           //更改电台下拉框的数据

changestv(1,true);                              //更改频道下拉框的数据

}

//取得频道数组

function gettvarray(obj)

{

     obj2 = $("tv_ct");                           //电台下拉框

     var tvp=obj.value;                          //省下拉框的值

     if(tvp=="")return ;

     obj2.options.length=0;                      //清空电台下拉框

     var z=false;                                //本省的数据是否已经从服务器得到了

    //遍历频道数组,查找本省数据是否已经获得

    for(var i=0;i<tvarray.length;i++)       

      {

           if(tvarray[i][0]==tvp)//找到

         {

                  z=true;

                  break;

           }

      }

     changestv(0,false,1);                       //更改频道下拉框的数据

     if(!z)                                      //本省数据没有,从服务器获得

       

         var post="p="+escape(tvp);                //构建省信息字符串

         Request.sendGET("TV.ashx?type=0&"+post,rectvprov,null,null,null);

                                                //发出获得数组的请求

       }

}

//获取某天的电视节目

function gettvset(url,day)

{

     if(!day)//如果没有日期,获取当前日期

     {

            var wday = new Date();

            day = wday.getDay ();

     }

     //发送请求

     Request.sendGET("TV.ashx?type=1&url="+$("tv_s3").value.split("-")[1]+"&day

     ="+day,rectv, null,null,faltv);

}

//成功接收服务器回调函数

function rectv(req,data)

{

     if(req.responseText=="")                    //返回空

     $("resulttv").innerHTML = "没有数据,请重新查询!";

     else

     $("resulttv").innerHTML = req.responseText;

}

//出现错误后的回调函数

function faltv(req,dat)

{

     alert("查询失败,请重试!!");

}

//初始化下拉列表框

gettvarray($("tvprov"));

12.5.5  服务器端处理模块Tv.ashx

由上面的脚本代码可知,服务器端需要完成两个任务:一是返回给客户端某个省的电台频道列表;另一个是返回给客户端某个电视台频道的节目时间表。第一个任务直接查询数据库即可完成。第二个任务则需要调用Thief类,远程获取节目表,然后再对节目表进行过滤。Tv.ashx是以type类型来区别两类任务的。Tv.ashx的实现代码如下:

<%@ WebHandler Language="C#" Class="TV" %>

using System;

using System.Collections.Generic;

using System.Text;

using System.Data;

using System.Text.RegularExpressions;

using System.Xml;

using System.Web;

using System.Xml.Xsl;

using System.IO;

//电视节目处理handler

public class TV : IHttpHandler

{

    public string TVList(string url, string day)

    {

         //获得某天的电视节目页面

         string str = Thief.Get("http://www.tvmao.com/ext/show_tv.jsp?c=" + url + "&day=" + day);

         //过滤数据

         str = str.Substring(str.IndexOf("<table id=\"main_body\">") + "<table id=\"main_body\">".Length);

         str = " <table cellspacing=0 cellpadding=0 style=\"font-size:12px\">" + str;

         string first = "";                                //日期导航

         if (day != "7")                                   //是周日

               first = str.Substring(0, str.IndexOf("星期日</a> </td>") + "星期日</a> </td>".Length);

         else

               first = str.Substring(0, str.IndexOf("id=\"curWeek\">星期日</span> </a> </td>") + "id=\"curWeek\">星期日</span></a> </td>".Length);

         first = Regex.Replace(first, "(?<=href=)(.*?=)([^&]*)(&day=)(\\d*)", "'javascript:gettvset(\"$2\",\"$4\");'", RegexOptions.IgnoreCase);

         if (day != "7")                                   //是周日

                str = str.Substring(str.IndexOf("星期日</a> </td>") + "星期日</a>
                     </td>".Length);

         else

              str = str.Substring(str.IndexOf("id=\"curWeek\">星期日</span></a> </td>") + "id=\"curWeek\">星期日</span></a> </td>".Length);

         str = str.Substring(0, str.IndexOf("</table>") + 8);

         str = Tools.DelLink(str);                         //删除超链接

         str = first + str;//合并

         str = Tools.delOption(str);                       //删除控制符

         if (str.IndexOf("TVMAO") != -1)                   //替换当没内容时的提示

               str = str.Replace("TVMAO", "QuCha.Net");

         return str;

    }

    //获得某省的电台数据

    public XmlDocument TVArray(string p)

    {

          Sql s = new Sql();

          //获得数据

          string str = s.GetDS("select prov, classname,channel,url from tv where
               prov='" + p + "'").GetXml();

          XmlDocument xml = new XmlDocument();

          xml.LoadXml(str);                    //转化成xml

          return xml;

    }

    public void ProcessRequest(HttpContext context)

    {

         if (context.Request["type"] == "0")   //获取某省的电台数据

         {

                context.Response.ContentType = "text/xml";

                context.Response.Write(TVArray(context.Request["p"]).OuterXml);

         }

         else                                  //获取某电台特定时间的电视节目时间表

         {

                context.Response.ContentType = "text/plain";

                context.Response.Write(TVList(context.Request["url"], context.Request
                     ["day"]));

         }

    }

    public bool IsReusable                   //不重用

    {

         get

         {

               return false;

         }

    }

}

查看所有评论(0)条】

最近评论



正在载入评论列表...
热点评论