本例通过提取搜索结果中的URL,发现google和baidu都指向同一个地址,则提取出来。在搜索过程中可以搜集有效搜索,以便以后再有同样的搜索可以先找到有效结果,大大提高搜索效率。
IE内核的浏览器中,js嵌入比较方便,只要通过函数execScript就可以在网页中插入JS代码,然后进一步进行操作。
本例通过提取搜索结果中的URL,发现 Google 和 baidu 指向同一个地址,则提取出来。对有效的搜索结果还可以加以记录,以便以后再有同样的搜索就能先找到之前搜集的有效结果,大大提高搜索效率。
下图一目了然地展示了其中的功能
不过,这些方便简单的功能要编写代码也着实花去不少功夫。
首先看看“此链接对于搜索有效”这个按钮怎插入到搜索结果中的:
(主体程序(即IE内核浏览器调用msscript.ocx)所用的js脚本和网页中的js脚本是两码事,这两个不同环境的脚本的变量和函数都是独立的,这一点在阅读的时候务必记住。网页的脚本的变量和函数在页面重新请求时就会消失,而使用msscript.ocx的IE内核浏览器中的js脚本则一直不发生变化。)
以 Google 为例
GoogleBrowser_OnNavigateComplete2
function GoogleBrowser_OnNavigateComplete2(url)
{
the_href="";
js="";
js+="function loopAllElements(node)\r\n";
js+="{\r\n";
js+="if(node.nodeType ==1)\r\n";
js+="{";
js+="if(node.tagName=='LI')\r\n";
js+="{";
js+="if(node.childNodes[0].tagName=='H3')\r\n";
js+="{\r\n";
js+="var a=node.childNodes[0].childNodes[0];\r\n";
js+="if(a.href!=undefined)\r\n";
js+="{\r\n";
js+="JavaScriptHelper.OnSearchItem('google',a.href,node.outerHTML,'"+SearchKeyText+"');\r\n";
js+="var button=document.createElement('INPUT');\r\n";
js+="button.type='BUTTON';\r\n";
js+="button.value='此链接对于搜索 \""+SearchKeyText+"\" 有效';\r\n";
js+="codeString='JavaScriptHelper.OnLike(\"'+a.href+'\",\""+SearchKeyText+"\");';\r\n";
js+="button.onclick=new Function(codeString);\r\n";
js+="node.appendChild(button);\r\n";
js+="}\r\n";
js+="}\r\n";
js+="}\r\n";
js+="}\r\n";
js+="var childrens=node.childNodes;\r\n";
js+="for(var i=0;i<childrens.length;i++)\r\n";
js+="{\r\n";
js+="loopAllElements(childrens[i]);\r\n";
js+="}\r\n";
js+="}\r\n";
js+="loopAllElements(document.getElementsByTagName('BODY')[0]);\r\n";
js+="JavaScriptHelper.OnOnePageFinish('google');\r\n";
//alert(js);
gb.ExecuteJavascript(js);
}
下面是搜索下一页的代码
GotoNextPage
function GotoNextPage()
{
SecondCount--;
if(SecondCount>0)
{
labelCurrent.Caption="当前第"+CurrentPageIndex+"页 "+SecondCount+"秒后自动下一页";
setTimeout("GotoNextPage();",1000);
return;
}
PageStarted=false;
the_href="";
js="var next_page_a;";
js+="function loopAllElements(node)\r\n";
js+="{\r\n";
js+="if(node.nodeType ==1)\r\n";
js+="{";
js+="if(node.innerText=='下一页')\r\n";
js+="{\r\n";
js+="if(node.href!=undefined)\r\n";
js+="{\r\n";
js+="next_page_a=node;\r\n";
js+="eval_code='the_href=\"';\r\n"
js+="eval_code+=node.href;\r\n"
js+="eval_code+='\"';\r\n"
js+="System.ExecuteScriptEval(eval_code,'Javascript');\r\n";
js+="return;\r\n";
js+="}\r\n";
js+="}\r\n";
js+="}\r\n";
js+="var childrens=node.childNodes;\r\n";
js+="for(var i=0;i<childrens.length;i++)\r\n";
js+="{\r\n";
js+="loopAllElements(childrens[i]);\r\n";
js+="}\r\n";
js+="}\r\n";
js+="next_page_a=null;\r\n";
js+="loopAllElements(document.getElementsByTagName('BODY')[0]);\r\n";
gb.ExecuteJavascript(js);
if(the_href=="")
return;
g_href=the_href;
the_href="";
bb.ExecuteJavascript(js);
if(the_href=="")
return;
PageStarted=0;
b_href=the_href;
gb.Navigate2(g_href);
bb.Navigate2(b_href);
CurrentPageIndex++;
labelCurrent.Caption="当前第"+CurrentPageIndex+"页";
if(CurrentPageIndex>=MaxPageCount)
{
panelSearch.Enabled=true;
}else
{
SecondCount=20;
setTimeout("GotoNextPage();",1000);
}
}
当点击“此链接对于搜索有效”这个按钮的消息响应则是这段代码,它向数据库中的 LikeUrl 表插入一条记录:
function OnLike(url,keyword_text)
{
q="INSERT INTO LikeUrl(key_text,url,short_desc)VALUES('"+keyword_text+"','"+url+"','')";
db2.query(q);
//重新刷新列表
RefreshList();
}
有4个对象需要说明一下:
1 dvm
这是根对象,下面的对象都通过这个对象展开,例如System对象是System=dvm.GetSharedObject("System");得到的,JavaScriptHelper对象是通过JavaScriptHelper=dvm.GetSharedObject('JavaScriptHelper').GetCodeObject();得到的。
2 System
这个对象是主体EXE程序的对系那个,它早从EXE程序相关内容,例如System.Exit()就是退出,更多操作可以参照这个主体EXE程序的VC代码。
3 JavaScriptHelper
这个对象操纵msscript.ocx,他可以让网页中的js代码调用ocx中的js函数。
4 MiniBrowser
这个是建议浏览器的类,用它可以创建n可浏览窗口。MiniBrowser::InvokeFunction可以让ocx的js代码调用网页中的函数。
有兴趣的朋友可以展开整个代码看看
#include <WindowsAPI.js>
//引入数据库
System.ExecuteScriptFile(System.GetAppPath()+"SystemDB.php","PHP");
db2=new dobject("SystemDatabaseManager");
db2.open(System.GetDataPath()+"GoogleBaidu.db");
//craete tables
q="CREATE TABLE LikeUrl(key_text varchar(255), url TEXT, short_desc TEXT);";
db2.query(q);
q="DROP TABLE UrlTemp";
db2.query(q);
q="CREATE TABLE UrlTemp(idx int,search_engine varchar(30), url TEXT, html TEXT, key_text varchar(255), short_desc TEXT);";
db2.query(q);
//布置主控界面
vcl=new dobject("vcl");
fn=System.GetWidgetPath()+"Main.dfm";
scope="GoogleBaidu";
share_all=true;
form=vcl.LoadFormFromDfmFile(fn,scope,share_all);
form.OnClose=function(Sender,Action){System.Exit();};
editKey=dvm.GetSharedObject(scope+".GoogleBaidu.editKey");
editKey.Text="duceland";
editKey2=dvm.GetSharedObject(scope+".GoogleBaidu.editKey2");
editKey2.Text="";
editKey2.OnChange=editKey2_OnChange;
cbAutoNextPage=dvm.GetSharedObject(scope+".GoogleBaidu.cbAutoNextPage");
editMaxPageCount=dvm.GetSharedObject(scope+".GoogleBaidu.editMaxPageCount");
labelCurrent=dvm.GetSharedObject(scope+".GoogleBaidu.labelCurrent");
btnSearch=dvm.GetSharedObject(scope+".GoogleBaidu.btnSearch");
btnSearch.OnClick=btnSearch_OnClick;
panelSearch=dvm.GetSharedObject(scope+".GoogleBaidu.panelSearch");
ListBox1=dvm.GetSharedObject(scope+".GoogleBaidu.ListBox1");
ListBox1.OnDblClick=ListBox1_OnDblClick;
dvm.GetSharedObject(scope+".GoogleBaidu.UpDown1").Associate=dvm.GetSharedObject(scope+".GoogleBaidu.editMaxPageCount");
Screen=new dobject("TScreen");
//布置google浏览界面
function GoogleBrowser_OnNavigateComplete2(url)
{
the_href="";
js="";
js+="function loopAllElements(node)\r\n";
js+="{\r\n";
js+="if(node.nodeType ==1)\r\n";
js+="{";
js+="if(node.tagName=='LI')\r\n";
js+="{";
js+="if(node.childNodes[0].tagName=='H3')\r\n";
js+="{\r\n";
js+="var a=node.childNodes[0].childNodes[0];\r\n";
js+="if(a.href!=undefined)\r\n";
js+="{\r\n";
js+="JavaScriptHelper.OnSearchItem('google',a.href,node.outerHTML,'"+SearchKeyText+"');\r\n";
js+="var button=document.createElement('INPUT');\r\n";
js+="button.type='BUTTON';\r\n";
js+="button.value='此链接对于搜索 \""+SearchKeyText+"\" 有效';\r\n";
js+="codeString='JavaScriptHelper.OnLike(\"'+a.href+'\",\""+SearchKeyText+"\");';\r\n";
js+="button.onclick=new Function(codeString);\r\n";
js+="node.appendChild(button);\r\n";
js+="}\r\n";
js+="}\r\n";
js+="}\r\n";
js+="}\r\n";
js+="var childrens=node.childNodes;\r\n";
js+="for(var i=0;i<childrens.length;i++)\r\n";
js+="{\r\n";
js+="loopAllElements(childrens[i]);\r\n";
js+="}\r\n";
js+="}\r\n";
js+="loopAllElements(document.getElementsByTagName('BODY')[0]);\r\n";
js+="JavaScriptHelper.OnOnePageFinish('google');\r\n";
//alert(js);
gb.ExecuteJavascript(js);
}
gb=new dobject("MiniBrowser");//browser for google
gb.OnClose=function(){System.Exit();};
gb.SetNoMenu();
gb.SetPosition(0,0,Screen.WorkAreaWidth/2,Screen.WorkAreaHeight-350);
gb.Show();
gb.OnNavigateComplete2=GoogleBrowser_OnNavigateComplete2;
gb.Navigate2("http://google.com");
//布置baidu浏览界面
function BaiduBrowser_OnNavigateComplete2(url)
{
the_href="";
js="";
js+="var match_td;\r\n";
js+="function loopAllElements(node)\r\n";
js+="{\r\n";
js+="if(node.tagName=='TD' && node.childNodes.length>1)\r\n";
js+="{\r\n";
js+="var a=node.childNodes[0];\r\n";
js+="if(a.tagName=='A')\r\n";
js+="{\r\n";
js+="if(node.outerHTML.indexOf('class=f')>0)\r\n";
js+="{\r\n";
js+="JavaScriptHelper.OnSearchItem('baidu',a.href,node.outerHTML,'"+SearchKeyText+"');\r\n";
js+="var button=document.createElement('INPUT');\r\n";
js+="button.type='BUTTON';\r\n";
js+="button.value='此链接对于搜索 \""+SearchKeyText+"\" 有效';\r\n";
js+="codeString='JavaScriptHelper.OnLike(\"'+a.href+'\",\""+SearchKeyText+"\");';\r\n";
js+="button.onclick=new Function(codeString);\r\n";
js+="node.insertBefore(button,node.childNodes[1]);\r\n";
js+="}\r\n";
js+="}\r\n";
js+="}\r\n";
js+="var childrens=node.childNodes;\r\n";
js+="for(var i=0;i<childrens.length;i++)\r\n";
js+="{\r\n";
js+="loopAllElements(childrens[i]);\r\n";
js+="}\r\n";
js+="}\r\n";
js+="match_td=false;\r\n";
js+="loopAllElements(document.getElementsByTagName('BODY')[0]);\r\n";
js+="JavaScriptHelper.OnOnePageFinish('baidu');\r\n";
//alert(js);
bb.ExecuteJavascript(js);
}
bb=new dobject("MiniBrowser");//browser for baidu
bb.OnClose=function(){System.Exit();};
bb.SetNoMenu();
bb.SetPosition(Screen.WorkAreaWidth/2,0,Screen.WorkAreaWidth/2,Screen.WorkAreaHeight-350);
bb.Show();
bb.OnNavigateComplete2=BaiduBrowser_OnNavigateComplete2;
bb.Navigate2("http://baidu.com");
//显示主控界面
form.Left=0;
form.Top=Screen.WorkAreaHeight-350;
form.Show();
vcl.SetTitleVisible(true);
vcl.SetTitle(form.Caption);
var AutoNextPage;
var MaxPageCount;
var CurrentPageIndex;
var SecondCount;
var PageStarted=false;
var SearchIndex=0;
var SearchKeyText="";
function btnSearch_OnClick(Sender)
{
SecondCount=20;
PageStarted=0;
SearchIndex=0;
SearchKeyText=editKey.Text;
//delete all data from temp
q="DELETE FROM UrlTemp;";
db2.query(q);
AutoNextPage=cbAutoNextPage.Checked;
MaxPageCount=parseInt(editMaxPageCount.Text);
js="document.forms[0].q.value='"+SearchKeyText+"';if(document.getElementsByName('f').length>0)document.f.submit();if(document.getElementsByName('gs').length>0)document.gs.submit();";
gb.ExecuteJavascript(js);
js="document.forms[0].wd.value='"+SearchKeyText+"';document.f.submit();";
bb.ExecuteJavascript(js);
panelSearch.Enabled=false;
setTimeout("GotoNextPage();",1000);
CurrentPageIndex=1;
labelCurrent.Caption="当前第1页 "+SecondCount+"秒后自动下一页";
}
function GotoNextPage()
{
SecondCount--;
if(SecondCount>0)
{
labelCurrent.Caption="当前第"+CurrentPageIndex+"页 "+SecondCount+"秒后自动下一页";
setTimeout("GotoNextPage();",1000);
return;
}
PageStarted=false;
the_href="";
js="var next_page_a;";
js+="function loopAllElements(node)\r\n";
js+="{\r\n";
js+="if(node.nodeType ==1)\r\n";
js+="{";
js+="if(node.innerText=='下一页')\r\n";
js+="{\r\n";
js+="if(node.href!=undefined)\r\n";
js+="{\r\n";
js+="next_page_a=node;\r\n";
js+="eval_code='the_href=\"';\r\n"
js+="eval_code+=node.href;\r\n"
js+="eval_code+='\"';\r\n"
js+="System.ExecuteScriptEval(eval_code,'Javascript');\r\n";
js+="return;\r\n";
js+="}\r\n";
js+="}\r\n";
js+="}\r\n";
js+="var childrens=node.childNodes;\r\n";
js+="for(var i=0;i<childrens.length;i++)\r\n";
js+="{\r\n";
js+="loopAllElements(childrens[i]);\r\n";
js+="}\r\n";
js+="}\r\n";
js+="next_page_a=null;\r\n";
js+="loopAllElements(document.getElementsByTagName('BODY')[0]);\r\n";
gb.ExecuteJavascript(js);
if(the_href=="")
return;
g_href=the_href;
the_href="";
bb.ExecuteJavascript(js);
if(the_href=="")
return;
PageStarted=0;
b_href=the_href;
gb.Navigate2(g_href);
bb.Navigate2(b_href);
CurrentPageIndex++;
labelCurrent.Caption="当前第"+CurrentPageIndex+"页";
if(CurrentPageIndex>=MaxPageCount)
{
panelSearch.Enabled=true;
}else
{
SecondCount=20;
setTimeout("GotoNextPage();",1000);
}
}
function ListBox1_OnDblClick(Sender)
{
idx=Sender.ItemIndex;
if(idx<0)
return;
text=Sender.Items.Get(idx);
pos=text.indexOf(" \t ");
if(pos>=0)
{
url=text.substring(pos+3,text.length);
System.MyShellExecute(url);
}
}
function editKey2_OnChange(Sender)
{
text=Sender.Text;
ListBox1.Items.Clear();
q="SELECT * FROM LikeUrl";
db2.query(q);
while(db2.fetch())
{
var kt=db2.get_array_data("key_text");
if(kt.indexOf(text)>=0)
{
var u=db2.get_array_data("url");
ListBox1.Items.Add(kt+" \t "+u);
}
}
}
ob=new dobject("MiniBrowser");//browser for output
ob.OnClose=function(){System.Exit();};
ob.SetNoMenu();
ob.SetPosition(628,Screen.WorkAreaHeight-350,Screen.WorkAreaWidth-628,350);
ob.Show();
ob.Navigate2("file://"+System.GetWidgetPath()+"output.htm");
function RefreshList()
{
ListBox1.Items.Clear();
q="SELECT * FROM LikeUrl";
db2.query(q);
while(db2.fetch())
{
var kt=db2.get_array_data("key_text");
var u=db2.get_array_data("url");
ListBox1.Items.Add(kt+" \t "+u);
}
}
RefreshList();
function OnLike(url,keyword_text)
{
q="INSERT INTO LikeUrl(key_text,url,short_desc)VALUES('"+keyword_text+"','"+url+"','')";
db2.query(q);
//重新刷新列表
RefreshList();
}
function replaceAll(text, s, t) {
var ss=s;
var tt=t;
var texttext=text;
var ret;
ret="";
idx=texttext.indexOf(ss);
while(idx>=0)
{
ret+=texttext.substring(0,idx);
ret+=tt;
texttext=texttext.substring(idx+ss.length,texttext.length);
idx=texttext.indexOf(ss);
if(idx%5==0)Sleep(0);//牺牲性能,却能防止90%以上的假死
}
ret+=texttext;
Sleep(0);//牺牲性能,却能防止90%以上的假死
return ret;
};
function xmlencode(string) {
var str=string;
str=replaceAll(str,'&','&');
str=replaceAll(str,'<','<');
str=replaceAll(str,'>','>');
str=replaceAll(str,'\'',''');
str=replaceAll(str,'"','"');
return str;
}
function xmldencode(string) {
var str=string;
str=replaceAll(str,'&','&');
str=replaceAll(str,'<','<');
str=replaceAll(str,'>','>');
str=replaceAll(str,''','\'');
str=replaceAll(str,'"','"');
return str;
}
function OnSearchItem(search_engine,url,html_text,keyword_text)
{
SearchIndex++;
html_text=xmlencode(html_text);
q="INSERT INTO UrlTemp(idx,search_engine,url,html,key_text,short_desc)VALUES("+SearchIndex+",'"+search_engine+"','"+url+"','"+html_text+"','"+keyword_text+"','')";
db2.query(q);
}
function OnOnePageFinish(from)
{
if(PageStarted===false)
{
//do noting
}else
{
PageStarted++;
if(PageStarted>=2)
{
//google+baidu
//查找url相同的
q="SELECT COUNT(*) as c,MAX(url) as u from UrlTemp GROUP BY url ORDER BY idx";
db2.query(q);
var output_html="";
var urls=new Array();
while(db2.fetch())
{
c=db2.get_array_data("c");
if(c>1)
{
url=db2.get_array_data("u");
urls.push(url);
}
}
for(var i=0;i<urls.length;i++)
{
q="SELECT * FROM UrlTemp where url='"+urls[i]+"' ORDER BY idx";
db2.query(q);
while(db2.fetch())
{
search_engine=db2.get_array_data("search_engine");
url=db2.get_array_data("url");
html=db2.get_array_data("html");
html=xmldencode(html);
output_html+="<div>【"+search_engine+" 搜索结果 : ";
output_html+="<a href='"+url+"' target='_blank'>"+url+"</a> 】<BR />";
output_html+=html;
output_html+="</div><BR />";
}
var btn="<INPUT type='BUTTON' value='此链接对于搜索 \""+SearchKeyText+"\" 有效'";
btn+=" onclick='Javascript:JavaScriptHelper.OnLike(\""+urls[i]+"\",\""+SearchKeyText+"\");'> ";
output_html+=btn;
output_html+=urls[i];
output_html+="<BR /><font color=gray>-----------Duceland 小应用引擎------</font><BR /><BR /><BR /><BR /><BR />";
}
ob.InvokeFunction("showSameUrl",output_html);
}
}
}
//纯网页二次处理http://markmail.org/message/ir2v2mwpwta27xgz#query:js%20new%20function+page:2+mid:ir2v2mwpwta27xgz+state:message
其中想说明的一点是,多个IE内核浏览器同时浏览的时候容易出现假死,而只要在繁重的JS计算代码中插入若干Sleep(0)让出处理机,则可防止90%以上的假死,不过使用过程中存在短暂时间不能动,不过大部分它会活过来的。Sleep(0)调用的是Windows API。下面是字符串替换函数,这是本例js计算最繁重的部分:如果用
function replaceAll(text, s, t) {
var ss=s;
var tt=t;
var texttext=text;
var ret;
ret="";
idx=texttext.indexOf(ss);
while(idx>=0)
{
ret+=texttext.substring(0,idx);
ret+=tt;
texttext=texttext.substring(idx+ss.length,texttext.length);
idx=texttext.indexOf(ss);
if(idx%5==0)Sleep(0);//牺牲性能,却能防止90%以上的假死
}
ret+=texttext;
Sleep(0);//牺牲性能,却能防止90%以上的假死
return ret;
};
function xmlencode(string) {
var str=string;
str=replaceAll(str,'&','&');
str=replaceAll(str,'<','<');
str=replaceAll(str,'>','>');
str=replaceAll(str,'\'',''');
str=replaceAll(str,'"','"');
return str;
}
不使用上述函数,而使用下面这个就极其容易假死:
function xmlencode(string) {
return string.replace(/\&/g,'&'+'amp;').replace(/</g,'&'+'lt;')
.replace(/>/g,'&'+'gt;').replace(/\'/g,'&'+'apos;').replace(/\"/g,'&'+'quot;');
}
【后记】google 和 baidu 已经很不错了,通过这2者相同的URL提取,则更加大大的提高准确性,不妨下一个玩玩吧
点击这里仅下载本例代码,下载后的.dwidget改名.zip文件解压即可
点击这里下载整个运行程序
点击这里下载这个IE内核浏览器源代码(不含msscript.ocx调用机制部分源代码,这部分是DLL形式提供的)