本页面由 Flash 保存计划 从 Internet Archive 存档还原 · 快照 2004-12-09 · 原址 http://bbs.flash8.net/forums/1789099/ShowPost.aspx ← Flash 保存计划
欢迎光临 闪吧论坛 登录 | 注册 | FAQ | 搜索
Print Search
帖子排序:    
帖子发起人:zas   发起时间:2006-01-05 12:38 下午   回复:5
zas 离线,最后访问时间:2006-1-12 18:07:00 zas

等级:Flash1

等级:FLASH1
注册:2002-07-06
发贴:92
积分:17
2006-01-05, 12:38 下午   IP 地址:已记录  报告  收藏  楼主
用flash实现基于搜索引擎的搜索 - 本地直接从百度获取LRC歌词



  • 由于安全性的原因,请下载到本地使用:
    地址(目标另存为) 代码:
    System.useCodepage = true;
    myLoadVars = new LoadVars();
    function lrcSearch(keyWord) {
    musicName = keyWord.slice(0, keyWord.indexOf(" "));
    myLoadVars.load("http://www.baidu.com/s?wd="+"[ti:"+keyWord);
    myLoadVars.onData = getLink;
    pageIndex = 1;
    }
    function getLink(src) {
    nextPageLink = "http://www.baidu.com/"+src.slice(src.lastIndexOf("href=", src.indexOf("下一页"))+5, src.lastIndexOf("><", src.indexOf("下一页")));
    linkData = src.split("快照");
    for (var i = 0; i<linkData.length; i++) {
    linkData[i] = linkData[i].slice(0, linkData[i].lastIndexOf("<a"));
    linkData[i] = linkData[i].slice(linkData[i].lastIndexOf("href=")+6);
    linkData[i] = linkData[i].slice(0, linkData[i].indexOf("\""));
    }
    linkIndex = 1;
    openLRCPage(linkData[0]);
    }
    function openLRCPage(url) {
    myLoadVars.load(url);
    myLoadVars.onData = getLRC;
    }
    function getLRC(src) {
    htmlData = src.slice(src.lastIndexOf("[ti:"+musicName));
    findEndTag();
    htmlData = htmlData.split("<br>").join("\n");
    htmlData = htmlData.split("<br />").join("\n");
    lrcData = htmlData.split(String.fromCharCode(10)).join("");
    tx_lrc.text = lrcData;
    }
    function findEndTag() {
    var lastIndex = htmlData.lastIndexOf("]");
    if (htmlData.slice(lastIndex-3, lastIndex-2) == "." && htmlData.slice(lastIndex-6, lastIndex-5) == ":") {
    var tmpBR = htmlData.slice(lastIndex);
    htmlData = htmlData.slice(0, lastIndex+tmpBR.indexOf("<br")+3);
    htmlData = htmlData.slice(0, htmlData.indexOf("</"));
    } else {
    htmlData = htmlData.slice(0, lastIndex);
    if (loopStart == undefined) {
    loopCount = 1;
    } else {
    delete loopStart;
    }
    if (loopCount<254) {
    loopStart = true;
    loopCount++;
    findEndTag();
    }
    }
    }
    function error() {
    if (nextPageLink != undefined) {
    if (linkIndex>linkData.length-2) {
    myLoadVars = new LoadVars();
    myLoadVars.load(nextPageLink);
    myLoadVars.onData = getLink;
    pageIndex++;
    linkIndex = 1;
    delete nextPageLink;
    } else {
    linkIndex++;
    openLRCPage(linkData[linkIndex-1]);
    }
    }
    }

    我们先来看第一句:
    System.useCodepage = true;
    这句主要的作用是让最后的结果不会变成乱码,默认情况下flash是按照UTF格式来解析所有加载的数据的,这在加载中文数据的时候会有些问题,只有数据在用UTF-8编码格式的时候才能被正确识别。因为很多页面(基本上现在90%的页面)并不是用UTF-8来保存的,所以要加上这句。这样才不会乱码。更详细的说明请参见flash帮助关于System.useCodepage的详细说明。反正在大部份情况下,如果你遇到乱码的问题都可以用这个来解决,使用 System.useCodepage = true 或者 System.useCodepage = false 来切换。 第二句:
    myLoadVars = new LoadVars();
    这是用来装载所有加载的数据的,等会加载的网页的数据(html源文件)都装在这里。基本上,要进行数据传输(例如和服务器程序交换变量数据或者从服务器上加载文件)的进候都要用到 LoadVars()、XML的数据传输/加载方法或者XMLSocket 。LoadVars() 是最基础的方法。 function lrcSearch(keyWord) {
    musicName = keyWord.slice(0, keyWord.indexOf(" "));
    myLoadVars.load("http://www.baidu.com/s?wd="+"[ti:"+keyWord);
    myLoadVars.onData = getLink;
    pageIndex = 1;
    } 这里定义了一个函数 lrcSearch(keyWord) 。呆会每次搜索不同歌词的时候都是从这里开始的,通过向这个函数发送不同的歌词名(如 lrcSearch("突然的自我")、 lrcSearch("童话")、lrcSearch("不得不爱")或者lrcSearch("我听这种音乐的时候最爱你"))来启动搜索。在这里,是所有代码的入口。
    它告诉flash:加载(下载) "http://www.baidu.com/s?wd="+"[ti:"+keyWord 的文件。keyWord 是刚刚上面所说的 "突然的自我" 等需要搜索的关键字。 当你在搜索引擎搜索内容的时候注意一下地栏的url,在百度中,它是类似于这样:
    http://www.baidu.com/s?wd=%5Bti%3A%CD%BB%C8%BB%B5%C4%D7%D4%CE%D2&cl=3
    你可以更改里面的"%5Bti%3A%CD%BB%C8%BB%B5%C4%D7%D4%CE%D2&cl=3"来完成不同的搜索,这里是刚刚输入的“[ti:披着羊皮的狼”的对应URL标准格式编码,你可以在浏览器中将这段文本转换成“[ti:突然的自我”试试。它会帮你自动转换成相应的URL来进行以后的工作(下载网页)。在flash中,也是一样的。所以你可以通过加载 http://www.baidu.com/s?wd=[ti:突然的自我 这样的URL来获得在浏览器中打开的文件(它们的html源代码)。也就是上面的那句:
    myLoadVars.load("http://www.baidu.com/s?wd="+"[ti:"+keyWord); 接着,myLoadVars.onData = getLink 定义了LoadVars的onData的事件。让 flash 在下载完网页后执行getLink这个函数的代码。
    LoadVars有两个事件(也就是当某一件事完成后要怎么样):LoadVars.onData 和 LoadVars.onLoad 。在这里,我们使用 LoadVars.onData。它的写法如下:
    my_lv.onData = function(src) {
    // 此处是您的语句
    }
    它定义了当下载完成的时候该执行的代码。src 是加载的原始(未分析)数据(在这里是下载的网页的源代码)。它直接定义了一个函数。你也可以将这个函数写在其它地方或者调用其它你已经写好的函数。也就是这样写:
    my_lv.onData = getLink 或者 my_lv.onData = getLink(src); (但注意不要这样写 my_lv.onData = getLink() ,因这样会丢失刚刚获得获得的网页源代码) musicName = keyWord.slice(0, keyWord.indexOf(" ")); 这一句我就不详细论述了,只告诉你它用来完成搜索中使用空格隔开关键字的功能。使用更多的用空隔间隔的关键字可以更快更准确的搜索到所要的内容,如加入歌手 "披着羊皮的狼 谭咏麟" 的结果就可能比 "披着羊皮的狼" 更准确,还可以对歌词的内容作界定,这可以将同名歌曲区别开来,例如"青春"这首歌曲就有5个以上的版本,像这样 "青春 你我都不会变不会变"(在这里,歌手的名字则可有可无,大部份情况下,无更好一些)。pageIndex = 1 并不是很重要,它用来完善一些可用性的事情,也就不多说了。 下面转到 getLink 函数:
    function getLink(src) {
    nextPageLink = "http://www.baidu.com/"+src.slice(src.lastIndexOf("href=", src.indexOf("下一页"))+5, src.lastIndexOf("><", src.indexOf("下一页")));
    linkData = src.split("快照");
    for (var i = 0; i<linkData.length; i++) {
    linkData[i] = linkData[i].slice(0, linkData[i].lastIndexOf("<a"));
    linkData[i] = linkData[i].slice(linkData[i].lastIndexOf("href=")+6);
    linkData[i] = linkData[i].slice(0, linkData[i].indexOf("\""));
    }
    linkIndex = 1;
    openLRCPage(linkData[0]);
    } 这是用来解析网页源文件的代码,我们用它来分析得到的搜索结果。
    第一句 nextPageLink = "http://www.baidu.com/"+src.slice(src.lastIndexOf("href=", src.indexOf("下一页"))+5, src.lastIndexOf("><", src.indexOf("下一页"))) 就不说了,它用来获得下一页的链接。 linkData = src.split("快照") 它将网页的源代码以"快照"作为参照拆为不同的段,然后放到数组中。事实上,linkData=new Array(); linkData = src.split("快照") 这样写更标准一些。 选取一个好的拆分关键字非常重要,它可以让你的运算量成倍降低(特别是要处理的数据量更大的时候,就更明显),在这里,我们使有"快照"这两个字,看看百度返回的结果:
    -----------------------------------------------------
    伍佰-突然的自我
    [ti:突然的自我] [al:伍佰&china blue 200 ] [offset:0] [00:05.00] 突然的自我 [00:12.87] [00:31.74]听见你说朝阳起又落 [00:37.62]晴雨难测道路是脚步多 [00:43.49]我已习惯你突然间的自我 [00:49.37]挥挥洒洒将自然看...
    www.musictea.com/music/lrc86407.htm?t=突 ... 4K 2005-12-24 - 百度快照
    www.musictea.com 上的更多结果 水晶手机信息技术网--wav铃声 黄小琥 - 突然的..
    [ti:突然的自我] [ar:黄小琥] [al:] [by:wolfpey] [offset:500] [00:02.67]《突然的自我》 [00:10.12...[ti:突然的自我] [ar:黄小琥] [al:] [by:wolfpey] [offset:500] [00:02.67]《突然的自我》 [00:10.12...
    www.zjnetcafe.com/html/7/60586.htm 5K 2005-10-14 - 百度快照
    -----------------------------------------------------
    这里只显示了两段文本,它有十个这样的文本块。分析一下,尽管每块文本的标题和内容都不同,但是每一段都会出现 "百度快照 " 这样的内容。在 Google 中则是这个: "网页快照 - 类似网页" 在百度中,你可以选择"百度快照"作为拆分的参照(如果查看源代码,也可以找到更多的参照),在 Google 中,"网页快照" 和 "类似网页" 都可以使用 ,在这里,我们以 Google 为实例,说明如何选取好的关键字的一个例子:(在百度中,这只是一个巧合,就不作为教程的参考了) 在 Google 搜索框中输入"[ti:披着羊皮的狼",然后查看一下网页的源代码(菜单:查看> 源文件 或者用右键弹出菜单)。它们和你在 flash 中获得的数据是一样的。找到每个重复类似的文本块的那一段源代码:(我们取第二段) *********************************
    <p class=g>
    <a class=l href="http://www.rixiu.com/fei5/11/1140657ae45bc98.html" target=_blank onmousedown="return clk(0,'res','2','')">郑源/披着羊皮的狼.LRC 飞舞歌词fei5.com</a><br>
    <font size=-1>郑源/披着羊皮的狼.LRC. <b>...</b> [ti:披着羊皮的狼] [ar:郑源] [al:我最<br>火] [by:fei5.com] [offset:-500] [00:01.00]-披着羊皮的狼- [00:04.00]歌手:郑<br>源[00:08.00]专辑:我最火[00:12.00]词曲:刀郎[00:16.00] <b>...</b><br>
    <font color=#008000>
    <span dir=ltr>www.rixiu.com/fei5/11/1140657ae45bc98.html</span> - 6k - 补充材料 - </font>
    <nobr><a class=fl href="http://72.14.203.104/search?q=cache:jsIjyqajvhcJ:www.rixiu.com/fei5/11/1140657ae45bc98.html+%5Bti:%E6%8A%AB%E7%9D%80%E7%BE%8A%E7%9A%AE%E7%9A%84%E7%8B%BC&hl=zh-CN" target=_blank>网页快照</a> -
    <a class=fl href="/search?hl=zh-CN&lr=&newwindow=1&q=related:www.rixiu.com/fei5/11/1140657ae45bc98.html">类似网页</a></nobr>
    </font>
    *********************************
    看看"网页快照" 和 "类似网页" 的位置, "类似网页"差不多是在结尾了,直觉上,用 "类似网页" 分割将更不会产生混淆,更完整(因为如果用 "网页快照" 分割出来的数据,属于这一段在"网页快照" 的一部份数据将会分割到下一段中,一个分割段中包含了两块文本的数据而造成混乱) 看看我们要取得什么,最终我们要得到的是指向最终页面的超链接。也就是这一段 " <a class=l href="http://www.rixiu.com/fei5/11/1140657ae45bc98.html" target=_blank onmousedown="return clk(0,'res','2','')">郑源/披着羊皮的狼.LRC 飞舞歌词fei5.com</a><br>" 事实上,我们只要取得这个超链接就可以了:
    http://www.rixiu.com/fei5/11/1140657ae45bc98.html 最终我们将用String的slice方法取得这个字符串,但在取之前我们必须找到字符串开始的位置"http://" 和最后结束的位置 "bc98.html" ,这就要用到String.indexOf()或String.lastIndexOf()方法。在这里,我们使用逆向查找的方法。也就是String.lastIndexOf()。它是从后向前搜索,如果找到,它将返回靠后的那个字符串的位置。参数将指定要搜索的字符串,它还有一个搜索起始位置的参数(在比较高级查找的时候有用),在这里我们只用第一个字符串参数,详细请看看官方帮助文档中的说明: my_str.lastIndexOf(substring, [startIndex])
    参数:
    substring 一个整数或字符串,指定要搜索的字符串。
    startIndex 一个可选整数,指定搜索 substring 的起始点。
    返回:
    指定子字符串的最后一个匹配项的位置,或 -1。
    说明:
    方法;在字符串中从右向左搜索,并返回调用此方法的字符串中在 startIndex 之前找到的 substring 的最后一个匹配项的索引。如果没有找到 substring,则此方法返回 -1。 for (var i = 0; i<linkData.length; i++) {
    ......
    }
    对每个区块执行同样的操作。现在我们只看看其中一块的处理。 看看用 "网页快照" ("快照" )截断的方式:
    *********************************
    </a> -
    <a class=fl href="/search?hl=zh-CN&lr=lang_zh-CN&newwindow=1&q=related:www.design-war.com/manage/download_counter.asp%3Fid%3D2262">类似网页</a></nobr>
    <p class=g>
    <a class=l href="http://www.rixiu.com/fei5/11/1140657ae45bc98.html" target=_blank onmousedown="return clk(0,'res','2','')">郑源/披着羊皮的狼.LRC 飞舞歌词fei5.com</a><br>
    <font size=-1>郑源/披着羊皮的狼.LRC. <b>...</b> [ti:披着羊皮的狼] [ar:郑源] [al:我最<br>火] [by:fei5.com] [offset:-500] [00:01.00]-披着羊皮的狼- [00:04.00]歌手:郑<br>源[00:08.00]专辑:我最火[00:12.00]词曲:刀郎[00:16.00] <b>...</b><br>
    <font color=#008000>
    <span dir=ltr>www.rixiu.com/fei5/11/1140657ae45bc98.html</span> - 6k - 补充材料 - </font>
    <nobr><a class=fl href="http://72.14.203.104/search?q=cache:jsIjyqajvhcJ:www.rixiu.com/fei5/11/1140657ae45bc98.html+%5Bti:%E6%8A%AB%E7%9D%80%E7%BE%8A%E7%9A%AE%E7%9A%84%E7%8B%BC&hl=zh-CN" target=_blank>网页快照
    </font>
    *********************************
    下面的处理事实上就是一层层剥离数据的过程。 第一句 linkData[i] = linkData[i].slice(0, linkData[i].lastIndexOf("<a")) 的作用是只取上面源代码的一部份用作后面的处理,这样有利于后面的操作和简化你的视野。 选取有特征的字符串在这里很重要。
    看看上面的这段代码,关于搜索结果的那一段("<font size=-1>郑源/披着羊皮的狼.LRC......c98.html</span> - 6k")都是不能作为特征进行数据搜索处理的,因为它们会随着搜索结果的不同而改变。所有可用的就是关于超链接的部份(搜索引擎不管如何更改他们的页面,点向最终页面的这个链接始终都是会存在的,随着时间的推移,在很长一段时间内也都是如此,这里有为你考虑到程序的寿命问题,也就是说,你写的这段程序在很长的一段时间内都是有用的)。
    也就是源代码中的"<a href= " 和"</a>"标签。在这里我们用了"<a"作为特征字符串并只取在这之前的数据。我们将从后面剥离最后一个超链接以使结果从后面开始第一个超链接就是我们想要的数据。
    linkData[i].lastIndexOf("<a") 找到最后一个 "<a"出现的位置,也就是在这个地方: ......补充材料 - </font><nobr><a class=fl href="http://72.14.203.104/ .....
    linkData[i] = linkData[i].slice(0, linkData[i].lastIndexOf("<a")) 取它之前的数据。也就是这一段: </a> - <a class=fl href="/search?hl=......6k - 补充材料 - </font><nobr>
    (补充一句,考到锚点和结果文字多少的情况,事实上用"</a"作为特征字符串处理可能更好一些,这样这一次处理的结果就剩下这段代码了):
    *********************************
    </a> -
    <a class=fl href="/search?hl=zh-CN&lr=lang_zh-CN&newwindow=1&q=related:www.design-war.com/manage/download_counter.asp%3Fid%3D2262">类似网页</a></nobr>
    <p class=g>
    <a class=l href="http://www.rixiu.com/fei5/11/1140657ae45bc98.html" target=_blank onmousedown="return clk(0,'res','2','')">郑源/披着羊皮的狼.LRC 飞舞歌词fei5.com</a>
    ********************************* 对比一下上面用"类似网页"截断的数据,要处理到这一步,就需要重复处理两次。(因为 "<a" 的超链接在从后向前查找的过程中,有出现两次,这就是为什么要选择 "网页快照" 作为我们截断重复区块的原因) 第二句 linkData[i] = linkData[i].slice(linkData[i].lastIndexOf("href=")+6) 从后面查找 "href="(现在最后的一个超链接区域就是我们想要的链接了,这就是为什么我们用lastIndexOf从后面搜索)。不过稍微不同的是,现在取在"href="之后的字符串(上一步是之前)。经过这次处理剩下的代码如下:
    *********************************
    http://www.rixiu.com/fei5/11/1140657ae45bc98.html" target=_blank onmousedown="return clk(0,'res','2','')">郑源/披着羊皮的狼.LRC 飞舞歌词fei5.com</a>
    ********************************* 第三句 linkData[i] = linkData[i].slice(0, linkData[i].indexOf("\"")) 取得第一个引号以前的字符串。这里我讲一下为什么不用 target= 或者.html 作为特征处理的原因,上面的代码实际上也可以将 target= 放在后面,也不会影响最终页面的结果。像这样:
    http://www.rixiu.com/fei5/11/1140657ae45bc98.html" onmousedown="return clk(0,'res','2','')" target=_blank>郑源/披着羊皮的狼.LRC
    飞舞歌词fei5.com</a>
    所以,它是不可识别和预知的。而.html 则并不是因为所有网页都是以.html作为结尾的,有些可能是.htm ,有些更可能是像?sl=11&word=aa这样动态生成的格式。(其实" 也并不是非常稳健的方式,因为有些不标准的网页可能将引号" 去除,这时候替代的方法是使用空格)
    *********************************
    http://www.rixiu.com/fei5/11/1140657ae45bc98.html
    ********************************* 现在最终我们得到了这个超链接。 通过上面的for (var i = 0; i<linkData.length; i++) { 循环,我们得到了这个页面的所有通过最终页面的链接(在百度中是10个)并将它们放入一个数组中。 (待续.......)
    [此贴子已经被作者于2006-1-7 23:15:45编辑过]
    一路一起:)       ōミ灬)~ ╮ミǐ.┊风的个人主页ヤooヾ _

    http://www.1617w.com/
    guoyl 离线,最后访问时间:2006-1-12 21:20:15 guoyl

    等级:Flash 2

    等级:FLASH 2
    注册:2004-03-24
    发贴:281
    积分:27
    2006-01-05, 13:10 下午   IP 地址:已记录  报告  收藏  第2楼

  • 坐沙发顶~
    蜜蜂嗡嗡嗡,闪吧勤打工。
    var str = "6775-6f-796c", nick = "";
    str = str.split("-").join("");
    for (var i = 0; i nick += chr(parseInt(str.substr(i, 2), 16));
    }
    trace(nick);
    uufeng 离线,最后访问时间:2006-1-12 23:13:01 uufeng

    等级:Flash 8


    等级:版主
    头衔:终点还是起点
    注册:2001-09-29
    发贴:7,094
    积分:180
    2006-01-05, 23:47 下午   IP 地址:已记录  报告  收藏  第3楼

  • [upload=swf]UploadFile/2006-1/200615234723926.swf[/upload]

    附件:
    序号 附件名称 类型 文件大小 上传时间 下载次数
    1 2006-1/200615234723926.swf Flash动画 44Kb 2006-01-05 4
    HBrO 离线,最后访问时间:2006-1-11 11:27:45 HBrO

    等级:Flash 3

    等级:FLASH 3
    注册:2005-10-12
    发贴:582
    积分:13
    2006-01-09, 13:17 下午   IP 地址:已记录  报告  收藏  第4楼
    Re:用flash实现基于搜索引擎的搜索 - 本地直接从百度获取LRC歌词

  • 回楼主:
    的确不错,善于观察网页特点,字符串方法也用得妥当.
    用AS分析html代码的确很难,幸亏楼主思维严谨,所以整个过程都没得挑.
    但是,毕竟是别人的网页,有些时候也很难掌握一些细节性的东西.
    所以我在另一个论坛跟FlashK讨论这个问题.讲的内容已经很长.鉴于你教程还没写完,我不希望让这帖子的内容太过混乱.所以文字就不复制在这里了.楼主有空可以到这里看看:
    http://www.blueidea.com/bbs/NewsDetail.asp?lp=1&id=2205817
    我前段时间做了个歌词播放器.但是就没有把搜索功能集成进去,于是有人建议我加这么个功能,然后几天前有人告诉我你这里写出了个搜歌词的程序,我便来研究了.前面主要是我讲歌词播放器的制作.所以,如果楼主想关注对你搜歌程序的讨论,可以直接跳到第三页.

    想写就写要写出技术
    哪怕没有人给我回复
    至少我还能够
    勇敢地面对孤独

    想写就写要写出成绩
    就算这主题没人气
    总有一天能看到
    为我顶帖的你
    猫大哥 在线,最后访问时间:2006-1-13 11:52:31 猫大哥

    等级:Flash 3


    等级:版主
    注册:2004-05-28
    发贴:509
    积分:86
    访问我的Blog
    昨天 09:54 上午   IP 地址:已记录  报告  收藏  第5楼
    Re:用flash实现基于搜索引擎的搜索 - 本地直接从百度获取LRC歌词

  • 顶上来.
    希望楼主继续将后面注释写完.待!!
    **教材发布区发帖及加分规则**
    zas 离线,最后访问时间:2006-1-12 18:07:00 zas

    等级:Flash1

    等级:FLASH1
    注册:2002-07-06
    发贴:92
    积分:17
    昨天 16:58 下午   IP 地址:已记录  报告  收藏  第6楼
    Re:用flash实现基于搜索引擎的搜索 - 本地直接从百度获取LRC歌词

  • 贴在这里了(有特殊字符标签,好像发贴的时候会报错):

    http://www.blueidea.com/bbs/NewsDetail.asp?lp=1&id=2422069
    一路一起:)       ōミ灬)~ ╮ミǐ.┊风的个人主页ヤooヾ _

    http://www.1617w.com/
    快速回复帖子

     




    标题: