浏览模式: 标准 | 列表分类:网站|ASP备忘
没有光驱的情况下装IIS
Submitted by on 2006, August 22, 10:04 PM
先要安装虚拟光驱DAEMON Tools,可以自己搜索下载的;然后下载IIS安装程序,一般为RAR压缩包,也不用解压缩。
打开虚拟光驱,它会要你给一个文件路径,你就把IIS的压缩包路径给它好了,例如:D:\IIS\IIS.rar,这里就不用管了。
然后到控制面版-添加或删除程序-添加或删除windows组件,打开选择IIS,下一步,它如果提示要插入光盘的话,就把虚拟光驱上的路径给它(是虚拟光驱的路径哦,已经不是rar压缩包的路径了,它已经变了,把rar变成了iso,在虚拟光驱上可以看到,例如:D:\IIS\IIS.ISO),然后继续下一步,就可以完成安装了。
打开虚拟光驱,它会要你给一个文件路径,你就把IIS的压缩包路径给它好了,例如:D:\IIS\IIS.rar,这里就不用管了。
然后到控制面版-添加或删除程序-添加或删除windows组件,打开选择IIS,下一步,它如果提示要插入光盘的话,就把虚拟光驱上的路径给它(是虚拟光驱的路径哦,已经不是rar压缩包的路径了,它已经变了,把rar变成了iso,在虚拟光驱上可以看到,例如:D:\IIS\IIS.ISO),然后继续下一步,就可以完成安装了。
ASP打造内容管理系统之模板技术乱谈
Submitted by on 2006, August 17, 6:01 AM
序:一直断断续续的写着这个东西。无奈网上对于这方面的文章很少,所以这里都是就谈谈个人制作过程中经验想法,仅供参考,如果有什么错误尽请指正。本意旨在抛砖引玉,希望有这方面经验的朋友共同探讨。这里主要对个人思路的阐述,文字表达能力不是很好,见谅。
设计这个系统的初衷是想程序和界面分离,那么在建立一个网站的时候只需要设计一套界面,加入系统提供的标签成为模板导入系统就完成,而且在内容组织及界面定义上有极高的自由度。制作者不需要接触任何程序。通过安装插件,在DW可视化编辑环境下,插入模板标签也象插入HTML代码一样轻松简单.如下面:
<cms:loop target="sort" name="allsort" cols="" rows="0">
<table width="400" border="0" cellspacing="1" cellpadding="0" style="border: 1px solid #999999;">
<tr>
<td bgcolor="#CCCCCC"><a href="<cms:urlsort>"><cms:sortname></a></td>
</tr>
<tr>
<td height="1" bgcolor="#666666"></td>
</tr>
<tr>
<td bgcolor="#CCCCCC">
<cms:loop taget="article" cols="10" name="articel">
·<a href="<cms:urltitle>"><cms:title lenth="20"></a><font color="#666666"><cms:date></font><br>
</cms:loop name="articel">
</td>
</tr>
</table>
</cms:loop name="allsort">
这是一个循环显示所有子栏目及子栏目下10条记录的模板文件其中<cms:***>即系统提供的标签。根据这些标签,生成文件效果如下:
我们经常在浏览网站时看到 ***.com/news/2004/06/08/2314342.html类似的网站,这个就是网站的后台管理程序根据数据库类容生成的静态html页面,其优点我就不用说了。我们的目的就是利用asp利用摸板页内容动态生成html等格式网页文件。其中主要用到的方法就是替换了。也就是程序据把摸板文件里定义好的标记替换成数据库里具体记录的内容并生成相应的页面文件。
模板替换的难点在于循环及嵌套循环。(如很常见的2级页面循环当前栏目的所有子栏目,每个栏目下又循环10条最新记录,有些有每行横向循环2-3个栏目等)以及循环中的参数传递及分析。其他的不过是个replace而已,通过一次有一次的从写代码,总结。这里我把创建页面的过程分为以下几个步骤。
这里画了个大流程图
今天就主要说说第一步:创建队列
1)什么使创建队列,就是告诉创建程序,我有哪些文件需要创建。然后程序根据创建队列集合逐个创建文件,这样一来使得生成文件这一行为非常对象化了.因为我们在管理内容是可能有以下动作,创建所有栏目及文章,创建某个栏目,创建某个栏目及文章,创建某个文章,创建我选定栏目或文章.引入了队列这个概念后我们只需要将需要创建的内容ID组合起来交给函数自己去做就行了.而无需去知道是什么行为.如我添加完一条记录后调用函数并送过去文章的栏目路径及文章ID,程序就根据这些数字逐个去创建相应的文件了.那么就算以后在扩展功能上也有很大的余地.如这样的形式 21,22,23,-201(这些数字主要是栏目和文章ID)为什么有负数呢?请往下看。
2)那么收到这个队列集合后呢,就该逐个根据ID好到数据库中去找该记录的相关参数来创建页面了。这里使用每自动刷新一次页面创建一个文件,应为如果一次要创建的文件很多的话一次性程序长期大量的占用CPU是不科学的,而且很可能脚本超时。
这里先张贴两个代码片断再做讲解。
<!-- #include file="_INC/Conn.asp" -->
Const spaceTime = 8
DIM FSO,WTO,FDER,SERVER_NAME
DBOpen()
Set FSO = Server.CreateObject("Scripting.FileSystemObject")
Call Main()
Set FSO = Nothing
DBClose()
"******************
"*******subs*******
"******************
DIM Global_Childs,Global_PageCutNum "Global variables,used by morethan one function
Sub Main()
DIM rsPrv,sqlPrv,j,k,Come
DIM Alignment,cStep,Steps,StepArr,CurrentStep,PrvPageCutNum
Global_PageCutNum = Request("Page")
cStep = Request("cStep")
Steps = Request("Steps")
Alignment = Request("Queue")
"控制上页进度调显示
If Steps <> 0 Then
DIM percent
percent = Int(cStep/Steps*100)
Response.Write("<script>parent.percent.width=""&percent&"%"</script>")
End If
"#中断?
"判断创建过程是否完成
If Int(cStep) = Int(Steps) and Steps <> "" Then
PrintInfo("<font color=red>全部创建完毕:</font> 共创建网页文件 "&Session("totalfiles")&"个; 耗时 "& FormatNumber((timer()-Session("StartTime"))*1000,3)&"毫秒")
Session("totalfiles") = ""
Session("StartTime") = ""
Exit Sub
End If
"第一次没有接收到创建队列,默认为创建全部内容,创建全队列
If Alignment = "" Then Call Alignment_All()
"取得当前进度及值
If Steps = "" Then Steps = uBound(StepArr) + 1 "Run once only
If Session("totalfiles") = "" Then Session("totalfiles") = uBound(StepArr)
CurrentStep = StepArr(cStep)
Set StepArr = nothing
"根据ID值大于0为创建栏目,负数为创建文章页面文件
DIM SortID,Forder,StorePath,ParentPath,Templet
If Int(CurrentStep) > -1 Then
Set rsPrv = Conn.ExeCute("Select * From ["& OP_TABLE_CLASS& "] Where SortID="& CurrentStep)
SortID = rsPrv("SortID")
Templet = rsPrv("Templet")
Forder = rsPrv("ForderName") "The sort"s storepath just like it"s fordername
Global_Childs = rsPrv("Childs")
ParentPath = rsPrv("ParentPath")
rsRemove(rsPrv)
If Global_PageCutNum = "" Then Call Creat_Forders(Forder)
"建立对象,调用创建文件主函数,并取得是分页与否参数
DIM myCreat,PageCutNum
Set myCreat = New Creat
myCreat.SortID = SortID
myCreat.Templet = Templet
myCreat.StorePath = Forder
myCreat.ParentPath = ParentPath
myCreat.reg = "<cms:loop>""循环功能目前只定义在非终极页面中
myCreat.CreatClass()
PrvPageCutNum = myCreat.PageCutNum"判断是否进入分页流程
Set myCreat = Nothing
Else
"小于0为创建文章页面
DIM TempletSun,ID
"文章ID记录为负数,转换为正数
ID = Int(CurrentStep)*-1
Set rsPrv = Conn.ExeCute("Select A.ID,S.TempletSun From ["& OP_TABLE_ARTICLE &"] A inner join ["& OP_TABLE_CLASS &"] S on S.SortID=A.SortID where A.ID="&ID)
TempletSun = rsPrv("TempletSun")
rsRemove(rsPrv)
Call CreatFinal(ID,TempletSun)
End If
"#中断
"参数传递进入下一次创建
Response.Write("<body onUnload="Creating.submit()">")
Response.Write("<form method="post" name="Creating"><input type="hidden" name="Come" value=""&Come&""><input type="hidden" name="cStep" value=""&cStep&""><input name="Steps" type="hidden" value=""&Steps&""><input type="hidden" name="Page" value=""&PrvPageCutNum&""><input type="hidden" name="Queue" value=""&Alignment&""></form>")
Response.Write("<meta http-equiv="refresh" content="&spaceTime&";url="LIB_Creat.asp">")
代码最后部分,这里输出一些HTML内容。
先看Response.Write("<meta http-equiv="refresh" content="&spaceTime&";url="LIB_Creat.asp">")
也就是程序执行到最后输出一断自动刷新页面的html代码。
再看Response.Write("<body onUnload="Creating.submit()">")
这里定义了页面在卸载的时候提交下面表单,本来可以通过querystring传递的,但以前看书上写好像伊最大只能传递256K数据还是多少,记不清了。所以这里通过form表单post方法提交,同时如果创建队列太长,如我网站有大小栏目10个有1000篇文章,某天我根新了模板要重新创建所有内容,呵呵,一次执行来完成,是不太可能的。这就象接力赛一样,一棒一棒往下传。一个文件一个文件的创建。这还有一个好处就是可以同时可以给用户返回当前进度和具体的创建过程中信息(可以看后么截图)如:如果用户某个模板标签定义错误,导致创建页面失败,等,这些信息都应该反馈给用户。
还有一点,以前参考看过一些类似的系统,也是通过刷新页面这种方式,但页面不停的刷新导致屏幕不停的闪烁,所以这里我把通过Creat.asp中长宽为0的iframe连接LIB_Creat.asp文件。解决创建是页面闪烁问题。
总结:将要创建的文件ID号组成队列结合交由创建函数对其逐个生成,队列中正数表示栏目ID负数表示文章ID。为了保证资源的占用,通过每刷新一次页面访问该函数来生成文件。
设计这个系统的初衷是想程序和界面分离,那么在建立一个网站的时候只需要设计一套界面,加入系统提供的标签成为模板导入系统就完成,而且在内容组织及界面定义上有极高的自由度。制作者不需要接触任何程序。通过安装插件,在DW可视化编辑环境下,插入模板标签也象插入HTML代码一样轻松简单.如下面:
<cms:loop target="sort" name="allsort" cols="" rows="0">
<table width="400" border="0" cellspacing="1" cellpadding="0" style="border: 1px solid #999999;">
<tr>
<td bgcolor="#CCCCCC"><a href="<cms:urlsort>"><cms:sortname></a></td>
</tr>
<tr>
<td height="1" bgcolor="#666666"></td>
</tr>
<tr>
<td bgcolor="#CCCCCC">
<cms:loop taget="article" cols="10" name="articel">
·<a href="<cms:urltitle>"><cms:title lenth="20"></a><font color="#666666"><cms:date></font><br>
</cms:loop name="articel">
</td>
</tr>
</table>
</cms:loop name="allsort">
这是一个循环显示所有子栏目及子栏目下10条记录的模板文件其中<cms:***>即系统提供的标签。根据这些标签,生成文件效果如下:
我们经常在浏览网站时看到 ***.com/news/2004/06/08/2314342.html类似的网站,这个就是网站的后台管理程序根据数据库类容生成的静态html页面,其优点我就不用说了。我们的目的就是利用asp利用摸板页内容动态生成html等格式网页文件。其中主要用到的方法就是替换了。也就是程序据把摸板文件里定义好的标记替换成数据库里具体记录的内容并生成相应的页面文件。
模板替换的难点在于循环及嵌套循环。(如很常见的2级页面循环当前栏目的所有子栏目,每个栏目下又循环10条最新记录,有些有每行横向循环2-3个栏目等)以及循环中的参数传递及分析。其他的不过是个replace而已,通过一次有一次的从写代码,总结。这里我把创建页面的过程分为以下几个步骤。
这里画了个大流程图
今天就主要说说第一步:创建队列
1)什么使创建队列,就是告诉创建程序,我有哪些文件需要创建。然后程序根据创建队列集合逐个创建文件,这样一来使得生成文件这一行为非常对象化了.因为我们在管理内容是可能有以下动作,创建所有栏目及文章,创建某个栏目,创建某个栏目及文章,创建某个文章,创建我选定栏目或文章.引入了队列这个概念后我们只需要将需要创建的内容ID组合起来交给函数自己去做就行了.而无需去知道是什么行为.如我添加完一条记录后调用函数并送过去文章的栏目路径及文章ID,程序就根据这些数字逐个去创建相应的文件了.那么就算以后在扩展功能上也有很大的余地.如这样的形式 21,22,23,-201(这些数字主要是栏目和文章ID)为什么有负数呢?请往下看。
2)那么收到这个队列集合后呢,就该逐个根据ID好到数据库中去找该记录的相关参数来创建页面了。这里使用每自动刷新一次页面创建一个文件,应为如果一次要创建的文件很多的话一次性程序长期大量的占用CPU是不科学的,而且很可能脚本超时。
这里先张贴两个代码片断再做讲解。
<!-- #include file="_INC/Conn.asp" -->
Const spaceTime = 8
DIM FSO,WTO,FDER,SERVER_NAME
DBOpen()
Set FSO = Server.CreateObject("Scripting.FileSystemObject")
Call Main()
Set FSO = Nothing
DBClose()
"******************
"*******subs*******
"******************
DIM Global_Childs,Global_PageCutNum "Global variables,used by morethan one function
Sub Main()
DIM rsPrv,sqlPrv,j,k,Come
DIM Alignment,cStep,Steps,StepArr,CurrentStep,PrvPageCutNum
Global_PageCutNum = Request("Page")
cStep = Request("cStep")
Steps = Request("Steps")
Alignment = Request("Queue")
"控制上页进度调显示
If Steps <> 0 Then
DIM percent
percent = Int(cStep/Steps*100)
Response.Write("<script>parent.percent.width=""&percent&"%"</script>")
End If
"#中断?
"判断创建过程是否完成
If Int(cStep) = Int(Steps) and Steps <> "" Then
PrintInfo("<font color=red>全部创建完毕:</font> 共创建网页文件 "&Session("totalfiles")&"个; 耗时 "& FormatNumber((timer()-Session("StartTime"))*1000,3)&"毫秒")
Session("totalfiles") = ""
Session("StartTime") = ""
Exit Sub
End If
"第一次没有接收到创建队列,默认为创建全部内容,创建全队列
If Alignment = "" Then Call Alignment_All()
"取得当前进度及值
If Steps = "" Then Steps = uBound(StepArr) + 1 "Run once only
If Session("totalfiles") = "" Then Session("totalfiles") = uBound(StepArr)
CurrentStep = StepArr(cStep)
Set StepArr = nothing
"根据ID值大于0为创建栏目,负数为创建文章页面文件
DIM SortID,Forder,StorePath,ParentPath,Templet
If Int(CurrentStep) > -1 Then
Set rsPrv = Conn.ExeCute("Select * From ["& OP_TABLE_CLASS& "] Where SortID="& CurrentStep)
SortID = rsPrv("SortID")
Templet = rsPrv("Templet")
Forder = rsPrv("ForderName") "The sort"s storepath just like it"s fordername
Global_Childs = rsPrv("Childs")
ParentPath = rsPrv("ParentPath")
rsRemove(rsPrv)
If Global_PageCutNum = "" Then Call Creat_Forders(Forder)
"建立对象,调用创建文件主函数,并取得是分页与否参数
DIM myCreat,PageCutNum
Set myCreat = New Creat
myCreat.SortID = SortID
myCreat.Templet = Templet
myCreat.StorePath = Forder
myCreat.ParentPath = ParentPath
myCreat.reg = "<cms:loop>""循环功能目前只定义在非终极页面中
myCreat.CreatClass()
PrvPageCutNum = myCreat.PageCutNum"判断是否进入分页流程
Set myCreat = Nothing
Else
"小于0为创建文章页面
DIM TempletSun,ID
"文章ID记录为负数,转换为正数
ID = Int(CurrentStep)*-1
Set rsPrv = Conn.ExeCute("Select A.ID,S.TempletSun From ["& OP_TABLE_ARTICLE &"] A inner join ["& OP_TABLE_CLASS &"] S on S.SortID=A.SortID where A.ID="&ID)
TempletSun = rsPrv("TempletSun")
rsRemove(rsPrv)
Call CreatFinal(ID,TempletSun)
End If
"#中断
"参数传递进入下一次创建
Response.Write("<body onUnload="Creating.submit()">")
Response.Write("<form method="post" name="Creating"><input type="hidden" name="Come" value=""&Come&""><input type="hidden" name="cStep" value=""&cStep&""><input name="Steps" type="hidden" value=""&Steps&""><input type="hidden" name="Page" value=""&PrvPageCutNum&""><input type="hidden" name="Queue" value=""&Alignment&""></form>")
Response.Write("<meta http-equiv="refresh" content="&spaceTime&";url="LIB_Creat.asp">")
代码最后部分,这里输出一些HTML内容。
先看Response.Write("<meta http-equiv="refresh" content="&spaceTime&";url="LIB_Creat.asp">")
也就是程序执行到最后输出一断自动刷新页面的html代码。
再看Response.Write("<body onUnload="Creating.submit()">")
这里定义了页面在卸载的时候提交下面表单,本来可以通过querystring传递的,但以前看书上写好像伊最大只能传递256K数据还是多少,记不清了。所以这里通过form表单post方法提交,同时如果创建队列太长,如我网站有大小栏目10个有1000篇文章,某天我根新了模板要重新创建所有内容,呵呵,一次执行来完成,是不太可能的。这就象接力赛一样,一棒一棒往下传。一个文件一个文件的创建。这还有一个好处就是可以同时可以给用户返回当前进度和具体的创建过程中信息(可以看后么截图)如:如果用户某个模板标签定义错误,导致创建页面失败,等,这些信息都应该反馈给用户。
还有一点,以前参考看过一些类似的系统,也是通过刷新页面这种方式,但页面不停的刷新导致屏幕不停的闪烁,所以这里我把通过Creat.asp中长宽为0的iframe连接LIB_Creat.asp文件。解决创建是页面闪烁问题。
总结:将要创建的文件ID号组成队列结合交由创建函数对其逐个生成,队列中正数表示栏目ID负数表示文章ID。为了保证资源的占用,通过每刷新一次页面访问该函数来生成文件。
用ASP生成XBM数字图片(可用来生成验证码)
Submitted by on 2006, August 17, 5:57 AM
XBM图片是一个纯文本的文件,可以用ASP来自动生成。可以用它来使用网站登陆的验证码;
我们用记事本打开该文件进行分析:
其文件结构为:
#define counter_width 48
#define counter_height 9
static unsigned char counter_bits[]={7c,3c,7c,3c,70,3c,fe,7c,fe,7c,78,7c,ee,ee,ee,ee,7c,ee,e0,ee,60,ee,74,ee,70,fe,30,fe,70,fe,38,ec,e0,ec,70,ec,1c,e0,ee,e0,70,e0,fe,7e,fe,7e,70,7e,fe,3c,7c,3c,70,3c}
文件扩展名为:.xbm
#define counter_width 48 ‘这儿定义的是图片的宽度,一般为8的倍数
#define counter_height 9 ‘这儿定义的是图片的高度,是任意的。
static unsigned char counter_bits[]={7c,3c,7c,3c,70,3c,fe,7c,fe,7c,78,7c,ee,ee,ee,ee,7c,ee,e0,ee,60,ee,74,ee,70,fe,30,fe,70,fe,38,ec,e0,ec,70,ec,1c,e0,ee,e0,70,e0,fe,7e,fe,7e,70,7e,fe,3c,7c,3c,70,3c} ‘这儿是图片用来显示内容的十六进制的代码
正如static unsigned char英文意思为静态的,无符号的,烧焦的。它只能用来显示黑白两种颜色。二进制中的1将来用显示为黑色,0为白色。
下面为0~9数字的二进制数组(其中的图片样式仅试用于本例。如果需要别的0~9数字样式,请另自行生成)
‘此处声明0~9绘图用数组
dim num(9,8)
‘数字0
num(0,0)="0x38"
num(0,1)="0x7c"
num(0,2)="0xee"
num(0,3)="0xee"
num(0,4)="0xee"
num(0,5)="0xee"
num(0,6)="0xee"
num(0,7)="0x7c"
num(0,8)="0x38"
‘数字1
num(1,0)="0x70"
num(1,1)="0x78"
num(1,2)="0x7c"
num(1,3)="0x74"
num(1,4)="0x70"
num(1,5)="0x70"
num(1,6)="0x70"
num(1,7)="0x70"
num(1,8)="0x70"
‘数字2
num(2,0)="0x7c"
num(2,1)="0xfe"
num(2,2)="0xee"
num(2,3)="0xe0"
num(2,4)="0x70"
num(2,5)="0x38"
num(2,6)="0x1c"
num(2,7)="0xfe"
num(2,8)="0xfe"
‘数字3
num(3,0)="0x7c"
num(3,1)="0xfe"
num(3,2)="0xee"
num(3,3)="0x60"
num(3,4)="0x30"
num(3,5)="0xe0"
num(3,6)="0xee"
num(3,7)="0xfe"
num(3,8)="0x7c"
‘数字4
num(4,0)="0x70"
num(4,1)="0x78"
num(4,2)="0x7c"
num(4,3)="0x76"
num(4,4)="0x77"
num(4,5)="0xff"
num(4,6)="0xff"
num(4,7)="0x70"
num(4,8)="0x70"
‘数字5
num(5,0)="0xfc"
num(5,1)="0xfc"
num(5,2)="0x0c"
num(5,3)="0x7e"
num(5,4)="0xfe"
num(5,5)="0xe0"
num(5,6)="0xee"
num(5,7)="0xfe"
num(5,8)="0x7c"
‘数字6
num(6,0)="0x78"
num(6,1)="0xfc"
num(6,2)="0x0e"
num(6,3)="0x6e"
num(6,4)="0xfe"
num(6,5)="0xee"
num(6,6)="0xee"
num(6,7)="0xfc"
num(6,8)="0x78"
‘数字7
num(7,0)="0xfe"
num(7,1)="0xfe"
num(7,2)="0x60"
num(7,3)="0x70"
num(7,4)="0x38"
num(7,5)="0x38"
num(7,6)="0x18"
num(7,7)="0x1c"
num(7,8)="0x1c"
‘数字8
num(8,0)="0x7c"
num(8,1)="0xfe"
num(8,2)="0xee"
num(8,3)="0x7c"
num(8,4)="0x7c"
num(8,5)="0xee"
num(8,6)="0xee"
num(8,7)="0xfe "
num(8,8)="0x7c"
‘数字9
num(9,0)="0x3c"
num(9,1)="0x7c"
num(9,2)="0xee"
num(9,3)="0xee"
num(9,4)="0xfe"
num(9,5)="0xec"
num(9,6)="0xe0"
num(9,7)="0x7e"
num(9,8)="0x3c"
下面实现这个的代码,把上面的数字数组(红色的)保存为funNum.asp
下面的文件部分,单独保存为一个ASP页
<%
response.Buffer=true
response.ExpiresAbsolute=now()-1
response.expires=0
response.CacheControl="no-cache"
%>
<!--#include file="funNum.asp"-->
<!--funNum.asp就是教程里那几个数组//-->
<%
const countHeight=9 ‘图片的高度
const countlength=6 ‘图片里数字的位数
const numBinBit=8 ‘这是数字数组里的二进制位数,好象只能使用八位以下的即11111111
const countWidth=48 ‘countlength*numBinBit得到
const imgtype="image/x-xbitmap"
dim countBody ‘图片信息
dim tmpcountbody ‘用于存放后面生成的图片数据
tmpcountbody=""
countBody="#define js_counter_width " & countWidth & vbCrLf
countBody=countBody & "#define js_counter_height " & countHeight & vbCrLf
countBody=countBody & "static unsigned char js_counter_bits[]={" & vbCrLf
dim numid ‘需要生成图片的数字
dim numarray() ‘将取得的numid分割成一个个的数字组成一维数组
numid="369245" ‘编写一个函数用来生成数字即可
if len(numid)<countLength then
for i=1 to countLength-len(numid)
numid="0" & numid
next
end if
redim numarray(len(numid)-1) ‘直接定义数组时要指字一整型数值,重定义数组大小时可使用表达式
for i=0 to ubound(numarray,1)
numarray(i)=mid(numid,i+1,1)
next
for i=0 to countHeight-1
for j=0 to countlength-1
tmpcountbody=tmpcountbody & num(numarray(j),i) & ","
next
next
tmpcountbody=left(tmpcountbody,len(tmpcountbody)-1)
countBody=countBody & tmpcountbody & "}"
response.contenttype=imgtype
response.write countBody
%>
我们用记事本打开该文件进行分析:
其文件结构为:
#define counter_width 48
#define counter_height 9
static unsigned char counter_bits[]={7c,3c,7c,3c,70,3c,fe,7c,fe,7c,78,7c,ee,ee,ee,ee,7c,ee,e0,ee,60,ee,74,ee,70,fe,30,fe,70,fe,38,ec,e0,ec,70,ec,1c,e0,ee,e0,70,e0,fe,7e,fe,7e,70,7e,fe,3c,7c,3c,70,3c}
文件扩展名为:.xbm
#define counter_width 48 ‘这儿定义的是图片的宽度,一般为8的倍数
#define counter_height 9 ‘这儿定义的是图片的高度,是任意的。
static unsigned char counter_bits[]={7c,3c,7c,3c,70,3c,fe,7c,fe,7c,78,7c,ee,ee,ee,ee,7c,ee,e0,ee,60,ee,74,ee,70,fe,30,fe,70,fe,38,ec,e0,ec,70,ec,1c,e0,ee,e0,70,e0,fe,7e,fe,7e,70,7e,fe,3c,7c,3c,70,3c} ‘这儿是图片用来显示内容的十六进制的代码
正如static unsigned char英文意思为静态的,无符号的,烧焦的。它只能用来显示黑白两种颜色。二进制中的1将来用显示为黑色,0为白色。
下面为0~9数字的二进制数组(其中的图片样式仅试用于本例。如果需要别的0~9数字样式,请另自行生成)
‘此处声明0~9绘图用数组
dim num(9,8)
‘数字0
num(0,0)="0x38"
num(0,1)="0x7c"
num(0,2)="0xee"
num(0,3)="0xee"
num(0,4)="0xee"
num(0,5)="0xee"
num(0,6)="0xee"
num(0,7)="0x7c"
num(0,8)="0x38"
‘数字1
num(1,0)="0x70"
num(1,1)="0x78"
num(1,2)="0x7c"
num(1,3)="0x74"
num(1,4)="0x70"
num(1,5)="0x70"
num(1,6)="0x70"
num(1,7)="0x70"
num(1,8)="0x70"
‘数字2
num(2,0)="0x7c"
num(2,1)="0xfe"
num(2,2)="0xee"
num(2,3)="0xe0"
num(2,4)="0x70"
num(2,5)="0x38"
num(2,6)="0x1c"
num(2,7)="0xfe"
num(2,8)="0xfe"
‘数字3
num(3,0)="0x7c"
num(3,1)="0xfe"
num(3,2)="0xee"
num(3,3)="0x60"
num(3,4)="0x30"
num(3,5)="0xe0"
num(3,6)="0xee"
num(3,7)="0xfe"
num(3,8)="0x7c"
‘数字4
num(4,0)="0x70"
num(4,1)="0x78"
num(4,2)="0x7c"
num(4,3)="0x76"
num(4,4)="0x77"
num(4,5)="0xff"
num(4,6)="0xff"
num(4,7)="0x70"
num(4,8)="0x70"
‘数字5
num(5,0)="0xfc"
num(5,1)="0xfc"
num(5,2)="0x0c"
num(5,3)="0x7e"
num(5,4)="0xfe"
num(5,5)="0xe0"
num(5,6)="0xee"
num(5,7)="0xfe"
num(5,8)="0x7c"
‘数字6
num(6,0)="0x78"
num(6,1)="0xfc"
num(6,2)="0x0e"
num(6,3)="0x6e"
num(6,4)="0xfe"
num(6,5)="0xee"
num(6,6)="0xee"
num(6,7)="0xfc"
num(6,8)="0x78"
‘数字7
num(7,0)="0xfe"
num(7,1)="0xfe"
num(7,2)="0x60"
num(7,3)="0x70"
num(7,4)="0x38"
num(7,5)="0x38"
num(7,6)="0x18"
num(7,7)="0x1c"
num(7,8)="0x1c"
‘数字8
num(8,0)="0x7c"
num(8,1)="0xfe"
num(8,2)="0xee"
num(8,3)="0x7c"
num(8,4)="0x7c"
num(8,5)="0xee"
num(8,6)="0xee"
num(8,7)="0xfe "
num(8,8)="0x7c"
‘数字9
num(9,0)="0x3c"
num(9,1)="0x7c"
num(9,2)="0xee"
num(9,3)="0xee"
num(9,4)="0xfe"
num(9,5)="0xec"
num(9,6)="0xe0"
num(9,7)="0x7e"
num(9,8)="0x3c"
下面实现这个的代码,把上面的数字数组(红色的)保存为funNum.asp
下面的文件部分,单独保存为一个ASP页
<%
response.Buffer=true
response.ExpiresAbsolute=now()-1
response.expires=0
response.CacheControl="no-cache"
%>
<!--#include file="funNum.asp"-->
<!--funNum.asp就是教程里那几个数组//-->
<%
const countHeight=9 ‘图片的高度
const countlength=6 ‘图片里数字的位数
const numBinBit=8 ‘这是数字数组里的二进制位数,好象只能使用八位以下的即11111111
const countWidth=48 ‘countlength*numBinBit得到
const imgtype="image/x-xbitmap"
dim countBody ‘图片信息
dim tmpcountbody ‘用于存放后面生成的图片数据
tmpcountbody=""
countBody="#define js_counter_width " & countWidth & vbCrLf
countBody=countBody & "#define js_counter_height " & countHeight & vbCrLf
countBody=countBody & "static unsigned char js_counter_bits[]={" & vbCrLf
dim numid ‘需要生成图片的数字
dim numarray() ‘将取得的numid分割成一个个的数字组成一维数组
numid="369245" ‘编写一个函数用来生成数字即可
if len(numid)<countLength then
for i=1 to countLength-len(numid)
numid="0" & numid
next
end if
redim numarray(len(numid)-1) ‘直接定义数组时要指字一整型数值,重定义数组大小时可使用表达式
for i=0 to ubound(numarray,1)
numarray(i)=mid(numid,i+1,1)
next
for i=0 to countHeight-1
for j=0 to countlength-1
tmpcountbody=tmpcountbody & num(numarray(j),i) & ","
next
next
tmpcountbody=left(tmpcountbody,len(tmpcountbody)-1)
countBody=countBody & tmpcountbody & "}"
response.contenttype=imgtype
response.write countBody
%>
网站生成静态页面,及网站数据采集的攻、防原理和策略
Submitted by on 2006, August 17, 5:48 AM
目前很多人都开始注重动态页面生成HTML页了,但选择哪种生成HTML的方法和防采集却不防搜索引擎的问题却经常困扰大家。解决此问题则是本文产生的原因。
首先祥细说一下常用的几种生成HTML的方法:
生成HTML方法主要步骤只有两个:
一、获取要生成的html文件的内容
二、将获取的html文件内容保存为html文件
我在这里主要说明的只是第一步:如何获取要生成的html文件的内容:
目前常用获取html文件的内容的方法有几下几种:
1、
CODE:str="<html标记>内容</html标记>"
str=str&"<html标记>内容</html标记><html标记>数据库读取内容....</html标记>....."
这种方法与是在脚本内写要生成的html内容,不太方便预览生成页面的内容,无法可视化布局页面,更改html模板时会更加复杂。
用这种方法的人很多,但我感觉这种方法是最不方便的。
2、
制作单独的HTML模板页,动态的内容用特定的字符作为标记(如:有人用$title$标记为网页标题),用ADODB.Stream或者Scripting.FileSystemObject将其模板内容载入,然后再用替换方法把原先定好的标记替换为动态内容(如:Replace(载入的模板内容,"$title$",rs("title" ) ) )。
3、
用XMLHTTP或serverXMLHTTP获取动态页所显示的HTML内容,
CODE:我常用的生成html文件的实例:
"-----------------翟振恺(小琦)
"weburl是要获取的动态页地址
"getHTTPPage(weburl)是获取动态页内容的函数
weburl="http://"&R...‘指定动态页地址
body=getHTTPPage(weburl)"用函数取到动态页地址的内容
"-----------------翟振恺(小琦)
此方法最大的好处就是不用费力气专门去写静态的模板页面,只是将原来就有的动态页面转换为HTML静态页面,但生成速度不是太快。
我常用的生成HTML的方法就是第3种:用XMLHTTP获取动态页生成的HTML内容,再用ADODB.Stream或者Scripting.FileSystemObject保存成html文件。
第二步是生成文件的方法:
ASP里常用的有用ADODB.Stream生成文件和Scripting.FileSystemObject生成文件两种
1、
Scripting.FileSystemObject生成文件方法:
CODE:"-----------------翟振恺(小琦)
Set fso = CreateObject("Scripting.FileSystemObject")
File=Server.MapPath("要生成文件路径和文件名.htm")
Set txt=fso.OpenTextFile(File,8,True)
data1="文件内容"用WriteLine方法生成文件
txt.WriteLine data1
data2="文件内容""用Write方法生成文件
txt.Write data2
txt.Close
txt.fso
"-----------------翟振恺(小琦)
2、
ADODB.Stream生成文件方法:
CODE:"-----------------翟振恺(小琦)
Dim objAdoStream
set objAdoStream = Server.createObject("ADODB.Stream")
objAdoStream.Type = 1
objAdoStream.Open()
objAdoStream.Write("文件内容")
objAdoStream.SaveToFile 要生成文件路径和文件名.htm,2
objAdoStream.Close()
"-----------------翟振恺(小琦)
再说一下我对HTML防采集却不防搜索引擎蜘蛛的一些经验:
我开发过几个采集程序,也研究过很多采集程序代码,所以对采集程序的原理还算是稍微有些了解。
先说一下采集原理:
采集程序的主要步骤如下:
一、获取被采集的页面的内容
二、从获取代码中提取所有用的数据
一、获取被采集的页面的内容
我目前所掌握的ASP常用获取被采集的页面的内容方法:
1、用serverXMLHTTP组件获取数据
CODE:Function GetBody(weburl)
"-----------------翟振恺(小琦)
"创建对象
Dim ObjXMLHTTP
Set ObjXMLHTTP=Server.CreateObject("MSXML2.serverXMLHTTP")
"请求文件,以异步形式
ObjXMLHTTP.Open "GET",weburl,False
ObjXMLHTTP.send
While ObjXMLHTTP.readyState <> 4
ObjXMLHTTP.waitForResponse 1000
Wend
"得到结果
GetBody=ObjXMLHTTP.responseBody
"释放对象
Set ObjXMLHTTP=Nothing
"-----------------翟振恺(小琦)
End Function
调用方法:
GetBody(文件的URLf地址)
2、或XMLHTTP组件获取数据
CODE:Function GetBody(weburl)
"-----------------翟振恺(小琦)
"创建对象
Set Retrieval = CreateObject("Microsoft.XMLHTTP")
With Retrieval
.Open "Get", weburl, False, "", ""
.Send
GetBody = .ResponseBody
End With
"释放对象
Set Retrieval = Nothing
"-----------------翟振恺(小琦)
End Function
调用方法:
GetBody(文件的URLf地址)
这样获取的数据内容还需要进行编码转换才可以使用
CODE:Function BytesToBstr(body,Cset)
"-----------------翟振恺(小琦)
dim objstream
set objstream = Server.CreateObject("adodb.stream")
objstream.Type = 1
objstream.Mode =3
objstream.Open
objstream.Write body
objstream.Position = 0
objstream.Type = 2
objstream.Charset = Cset
BytesToBstr = objstream.ReadText
objstream.Close
set objstream = nothing
"-----------------翟振恺(小琦)
End Function
调用方法:BytesToBstr(要转换的数据,编码)"编码常用为GB2312和UTF-8
二、从获取代码中提取所有用的数据
目前我掌握的方法有:
1、用ASP内置的MID函数截取需要的数据
CODE:Function body(wstr,start,over)
"-----------------翟振恺(小琦)
start=Newstring(wstr,start)
"设置需要处理的数据的唯一的开始标记
over=Newstring(wstr,over)
"和start相对应的就是需要处理的数据的唯一的结束标记
body=mid(wstr,start,over-start)
"设置显示页面的范围
"-----------------翟振恺(小琦)
End Function
调用方法:body(被采集的页面的内容,开始标记,结束标记)
2、用正则获取需要的数据
CODE:Function body(wstr,start,over)
"-----------------翟振恺(小琦)
Set xiaoqi = New Regexp"设置配置对象
xiaoqi.IgnoreCase = True"忽略大小写
xiaoqi.Global = True"设置为全文搜索
xiaoqi.Pattern = "”&start&“.+?”&over&“""正则表达式
Set Matches =xiaoqi.Execute(wstr)"开始执行配置
set xiaoqi=nothing
body=""
For Each Match in Matches
body=body&Match.Value "循环匹配
Next
"-----------------翟振恺(小琦)
End Function
调用方法:body(被采集的页面的内容,开始标记,结束标记)
采集程序祥细思路:
1、取得网站的分页列表页的每页地址
目前绝大部分动态网站的分页地址都有规则,如:
动态页
第一页:index.asp?page=1
第二页:index.asp?page=2
第三页:index.asp?page=3
.....
静态页
第一页:page_1.htm
第二页:page_2.htm
第三页:page_3.htm
.....
取得网站的分页列表页的每页地址,只需要用变量替代每页地址的变化的字符即可如:page_<%="&page&"%>.htm
2、获取被采集网站的分页列表页内容
3、从分页列表代码中提取被采集的内容页面的URL连接地址
绝大部分分页页面里的内容页连接也有固定规则,如:
<a href="url1">连接1</a> <br>
<a href="url2">连接2</a> <br>
<a href="url3">连接3</a> <br>
用以下代码就可以获得一个URL连接集合
CODE:"-----------------翟振恺(小琦)
Set xiaoqi = New Regexp
xiaoqi.IgnoreCase = True
xiaoqi.Global = True
xiaoqi.Pattern = ””“.+?”““
Set Matches =xiaoqi.Execute(页面列表内容)
set xiaoqi=nothing
url=""
For Each Match in Matches
url=url&Match.Value
Next
"-----------------翟振恺(小琦)
4、取得被采集的内容页面内容,根据”提取标记“从被采集的内容页面分别截取要取得的数据
因为是动态生成的页面,大多数内容页面内都有相同的html标记,我们可以根据这些有规则的标记提取需要的各个部分的内容。
如:
每个页面都有网页标题<title>网页标题</title>,用我上面写的MID截取函数就可以获得<title></title>之间的值,也可以用正则表达式来获得。
例:body("<title>网页标题</title>","<title>","</title>")
介绍完采集器的祥细原理后,就开始说一下防采集的策略。
目前防采集的方法有很多种,先介绍一下常见防采集策略方法和它的弊端及采集对策:
一、判断一个IP在一定时间内对本站页面的访问次数,如果明显超过了正常人浏览速度,就拒绝此IP访问
弊端:
1、此方法只适用于动态页面,如:asp\jsp\php等...静态页面无法判断某个IP一定时间访问本站页面的次数
2、此方法会严重影响搜索引擎蜘蛛对其收录,因为搜索引擎蜘蛛收录时,浏览速度都会比较快而且是多线程。此方法也会拒绝搜索引擎蜘蛛收录站内文件
采集对策:只能放慢采集速度,或者不采
建议:做个搜索引擎蜘蛛的IP库,只允许搜索引擎蜘蛛快速浏览站内内容。搜索引擎蜘蛛的IP库的收集,也不太容易,一个搜索引擎蜘蛛,也不一定只有一个固定的IP地址。
评论:此方法对防采集比较有效,但却会影响搜索引擎对其收录。
二、用javascript加密内容页面
弊端:此方法适用于静态页面,但会严重影响搜索引擎对其收录情况,搜索引擎收到到的内容,也都是加密后的内容
采集对策:建议不采,如非要采,就把解密码的JS脚本也采下来。
建议:目前没有好的改良建议
评论:建议指望搜索引擎带流量的站长不要使用此方法。
三、把内容页面里的特定标记替换为”特定标记+隐藏版权文字“
弊端:此方法弊端不大,仅仅会增加一点点的页面文件大小,但容易反采集
采集对策:把采集来的含有隐藏版权文字内容的版权文字替掉,或替换成自己的版权。
建议:目前没有好的改良建议
评论:自己感觉实用价值不大,就算是加上随机的隐藏文字,也等于画蛇添足。
四、只允许用户登陆后才可以浏览
弊端:此方法会严重影响搜索引擎蜘蛛对其收录
采集对策:目前落伍已经有人发了对策文章 ,具体对策就看这个吧《ASP小偷程序如何利用XMLHTTP实现表单的提交以及cookies或session的发送》
建议:目前没有好的改良建议
评论:建议指望搜索引擎带流量的站长不要使用此方法。不过此方法防一般的采集程序,还是有点效果的。
五、用javascript、vbscript脚本做分页
弊端:影响搜索引擎对其收录
采集对策:分析javascript、vbscript脚本,找出其分页规则,自己做个对应此站的分页集合页即可。
建议:目前没有好的改良建议
评论:感觉懂点脚本语言的人都能找出其分页规则
六、只允许通过本站页面连接查看,如:Request.ServerVariables("HTTP_REFERER")
弊端:影响搜索引擎对其收录
采集对策:不知道能不能模拟网页来源。。。。目前我没有对应此方法的采集对策
建议:目前没有好的改良建议
评论:建议指望搜索引擎带流量的站长不要使用此方法。不过此方法防一般的采集程序,还是有点效果的。
从以上可以看出,目前常用的防采集方法,要么会对搜索引擎收录有较大影响,要么防采集效果不好,起不到防采集的效果。那么,还有没有一种有效防采集,而又不影响搜索引擎收录的方法呢?那就请继续往下看吧,精彩的地方马上呈献给大家。
下面就是我的防采集策略,防采集而又不防搜索引擎
从前面的我讲的采集原理大家可以看出,绝大多数采集程序都是靠分析规则来进行采集的,如分析分页文件名规则、分析页面代码规则。
一、分页文件名规则防采集对策
大部分采集器都是靠分析分页文件名规则,进行批量、多页采集的。如果别人找不出你的分页文件的文件名规则,那么别人就无法对你的网站进行批量多页采集。
实现方法:
我认为用MD5加密分页文件名是一个比较好的方法,说到这里,有人会说,你用MD5加密分页文件名,别人根据此规则也可以模拟你的加密规则得到你的分页文件名。
我要指出的是我们加密分页文件名时,不要只加密文件名变化的部分
如果I代表分页的页码,那么我们不要这样加密
page_name=Md5(I,16)&".htm"
最好给要加密的页码上再跟进一个或多个字符,如:page_name=Md5(I&"任意一个或几个字母",16)&".htm"
因为MD5是无法反解密的,别人看到的会页字母是MD5加密后的结果,所以加人也无法知道你在 I 后面跟进的字母是什么,除非他用暴力****MD5,不过不太现实。
二、页面代码规则防采集对策
如果说我们的内容页面无代码规则,那么别人就无法从你的代码中提取他们所需要的一条条内容。
所以我们要的这一步做到防采集,就要使代码无规则。
实现方法:
使对方需要提取的标记随机化
1、定制多个网页模板,每个网页模板里的重要HTML标记不同,呈现页面内容时,随机选取网页模板,有的页面用CSS+DIV布局,有的页面用table布局,此方法是麻烦了点,一个内容页面,要多做几个模板页面,不过防采集本身就是一件很烦琐的事情,多做一个模板,能起到防采集的作用,对很多人来说,都是值得的。
2、如果嫌上面的方法太麻烦,把网页里的重要HTML标记随机化,也可以。
做的网页模板越多,html代码越是随机化,对方分析起内容代码时,就越麻烦,对方针对你的网站专门写采集策略时,难度就更大,在这个时候,绝大部分人,都会知难而退,因为这此人就是因为懒,才会采集别人网站数据嘛~~~再说一下,目前大部分人都是拿别人开发的采集程序去采集数据,自己开发采集程序去采集数据的人毕竟是少数。
还有些简单的思路提供给大家:
1、把对数据采集者重要,而对搜索引擎不重要的内容用客户端脚本显示
2、把一页数据,分为N个页面显示,也是加大采集难度的方法
3、用更深层的连接,因为目前大部分采集程序只能采集到网站内容的前3层,如果内容所在的连接层更深,也可以避免被采集。不过这样可能会给客户造成浏览上的不便。
如:
大多网站都是 首页----内容索引分页----内容页
如果改成:
首页----内容索引分页----内容页入口----内容页
注:内容页入口最好能加上自动转入内容页的代码
CODE:<meta http-equiv="refresh" content="6;url=内容页(http://www.xiaoqi.net)&...
其实,只要做好防采集的第一步(加密分页文件名规则),防采集的效果就已经不错了,还是建议两条反采集方法同时使用,给采集者增加采集难度,使得他们知难页退。
至此,全文完,欢迎大家在此讨论与此相关技术,谢谢!
作者:翟振恺(小琦)
首先祥细说一下常用的几种生成HTML的方法:
生成HTML方法主要步骤只有两个:
一、获取要生成的html文件的内容
二、将获取的html文件内容保存为html文件
我在这里主要说明的只是第一步:如何获取要生成的html文件的内容:
目前常用获取html文件的内容的方法有几下几种:
1、
CODE:str="<html标记>内容</html标记>"
str=str&"<html标记>内容</html标记><html标记>数据库读取内容....</html标记>....."
这种方法与是在脚本内写要生成的html内容,不太方便预览生成页面的内容,无法可视化布局页面,更改html模板时会更加复杂。
用这种方法的人很多,但我感觉这种方法是最不方便的。
2、
制作单独的HTML模板页,动态的内容用特定的字符作为标记(如:有人用$title$标记为网页标题),用ADODB.Stream或者Scripting.FileSystemObject将其模板内容载入,然后再用替换方法把原先定好的标记替换为动态内容(如:Replace(载入的模板内容,"$title$",rs("title" ) ) )。
3、
用XMLHTTP或serverXMLHTTP获取动态页所显示的HTML内容,
CODE:我常用的生成html文件的实例:
"-----------------翟振恺(小琦)
"weburl是要获取的动态页地址
"getHTTPPage(weburl)是获取动态页内容的函数
weburl="http://"&R...‘指定动态页地址
body=getHTTPPage(weburl)"用函数取到动态页地址的内容
"-----------------翟振恺(小琦)
此方法最大的好处就是不用费力气专门去写静态的模板页面,只是将原来就有的动态页面转换为HTML静态页面,但生成速度不是太快。
我常用的生成HTML的方法就是第3种:用XMLHTTP获取动态页生成的HTML内容,再用ADODB.Stream或者Scripting.FileSystemObject保存成html文件。
第二步是生成文件的方法:
ASP里常用的有用ADODB.Stream生成文件和Scripting.FileSystemObject生成文件两种
1、
Scripting.FileSystemObject生成文件方法:
CODE:"-----------------翟振恺(小琦)
Set fso = CreateObject("Scripting.FileSystemObject")
File=Server.MapPath("要生成文件路径和文件名.htm")
Set txt=fso.OpenTextFile(File,8,True)
data1="文件内容"用WriteLine方法生成文件
txt.WriteLine data1
data2="文件内容""用Write方法生成文件
txt.Write data2
txt.Close
txt.fso
"-----------------翟振恺(小琦)
2、
ADODB.Stream生成文件方法:
CODE:"-----------------翟振恺(小琦)
Dim objAdoStream
set objAdoStream = Server.createObject("ADODB.Stream")
objAdoStream.Type = 1
objAdoStream.Open()
objAdoStream.Write("文件内容")
objAdoStream.SaveToFile 要生成文件路径和文件名.htm,2
objAdoStream.Close()
"-----------------翟振恺(小琦)
再说一下我对HTML防采集却不防搜索引擎蜘蛛的一些经验:
我开发过几个采集程序,也研究过很多采集程序代码,所以对采集程序的原理还算是稍微有些了解。
先说一下采集原理:
采集程序的主要步骤如下:
一、获取被采集的页面的内容
二、从获取代码中提取所有用的数据
一、获取被采集的页面的内容
我目前所掌握的ASP常用获取被采集的页面的内容方法:
1、用serverXMLHTTP组件获取数据
CODE:Function GetBody(weburl)
"-----------------翟振恺(小琦)
"创建对象
Dim ObjXMLHTTP
Set ObjXMLHTTP=Server.CreateObject("MSXML2.serverXMLHTTP")
"请求文件,以异步形式
ObjXMLHTTP.Open "GET",weburl,False
ObjXMLHTTP.send
While ObjXMLHTTP.readyState <> 4
ObjXMLHTTP.waitForResponse 1000
Wend
"得到结果
GetBody=ObjXMLHTTP.responseBody
"释放对象
Set ObjXMLHTTP=Nothing
"-----------------翟振恺(小琦)
End Function
调用方法:
GetBody(文件的URLf地址)
2、或XMLHTTP组件获取数据
CODE:Function GetBody(weburl)
"-----------------翟振恺(小琦)
"创建对象
Set Retrieval = CreateObject("Microsoft.XMLHTTP")
With Retrieval
.Open "Get", weburl, False, "", ""
.Send
GetBody = .ResponseBody
End With
"释放对象
Set Retrieval = Nothing
"-----------------翟振恺(小琦)
End Function
调用方法:
GetBody(文件的URLf地址)
这样获取的数据内容还需要进行编码转换才可以使用
CODE:Function BytesToBstr(body,Cset)
"-----------------翟振恺(小琦)
dim objstream
set objstream = Server.CreateObject("adodb.stream")
objstream.Type = 1
objstream.Mode =3
objstream.Open
objstream.Write body
objstream.Position = 0
objstream.Type = 2
objstream.Charset = Cset
BytesToBstr = objstream.ReadText
objstream.Close
set objstream = nothing
"-----------------翟振恺(小琦)
End Function
调用方法:BytesToBstr(要转换的数据,编码)"编码常用为GB2312和UTF-8
二、从获取代码中提取所有用的数据
目前我掌握的方法有:
1、用ASP内置的MID函数截取需要的数据
CODE:Function body(wstr,start,over)
"-----------------翟振恺(小琦)
start=Newstring(wstr,start)
"设置需要处理的数据的唯一的开始标记
over=Newstring(wstr,over)
"和start相对应的就是需要处理的数据的唯一的结束标记
body=mid(wstr,start,over-start)
"设置显示页面的范围
"-----------------翟振恺(小琦)
End Function
调用方法:body(被采集的页面的内容,开始标记,结束标记)
2、用正则获取需要的数据
CODE:Function body(wstr,start,over)
"-----------------翟振恺(小琦)
Set xiaoqi = New Regexp"设置配置对象
xiaoqi.IgnoreCase = True"忽略大小写
xiaoqi.Global = True"设置为全文搜索
xiaoqi.Pattern = "”&start&“.+?”&over&“""正则表达式
Set Matches =xiaoqi.Execute(wstr)"开始执行配置
set xiaoqi=nothing
body=""
For Each Match in Matches
body=body&Match.Value "循环匹配
Next
"-----------------翟振恺(小琦)
End Function
调用方法:body(被采集的页面的内容,开始标记,结束标记)
采集程序祥细思路:
1、取得网站的分页列表页的每页地址
目前绝大部分动态网站的分页地址都有规则,如:
动态页
第一页:index.asp?page=1
第二页:index.asp?page=2
第三页:index.asp?page=3
.....
静态页
第一页:page_1.htm
第二页:page_2.htm
第三页:page_3.htm
.....
取得网站的分页列表页的每页地址,只需要用变量替代每页地址的变化的字符即可如:page_<%="&page&"%>.htm
2、获取被采集网站的分页列表页内容
3、从分页列表代码中提取被采集的内容页面的URL连接地址
绝大部分分页页面里的内容页连接也有固定规则,如:
<a href="url1">连接1</a> <br>
<a href="url2">连接2</a> <br>
<a href="url3">连接3</a> <br>
用以下代码就可以获得一个URL连接集合
CODE:"-----------------翟振恺(小琦)
Set xiaoqi = New Regexp
xiaoqi.IgnoreCase = True
xiaoqi.Global = True
xiaoqi.Pattern = ””“.+?”““
Set Matches =xiaoqi.Execute(页面列表内容)
set xiaoqi=nothing
url=""
For Each Match in Matches
url=url&Match.Value
Next
"-----------------翟振恺(小琦)
4、取得被采集的内容页面内容,根据”提取标记“从被采集的内容页面分别截取要取得的数据
因为是动态生成的页面,大多数内容页面内都有相同的html标记,我们可以根据这些有规则的标记提取需要的各个部分的内容。
如:
每个页面都有网页标题<title>网页标题</title>,用我上面写的MID截取函数就可以获得<title></title>之间的值,也可以用正则表达式来获得。
例:body("<title>网页标题</title>","<title>","</title>")
介绍完采集器的祥细原理后,就开始说一下防采集的策略。
目前防采集的方法有很多种,先介绍一下常见防采集策略方法和它的弊端及采集对策:
一、判断一个IP在一定时间内对本站页面的访问次数,如果明显超过了正常人浏览速度,就拒绝此IP访问
弊端:
1、此方法只适用于动态页面,如:asp\jsp\php等...静态页面无法判断某个IP一定时间访问本站页面的次数
2、此方法会严重影响搜索引擎蜘蛛对其收录,因为搜索引擎蜘蛛收录时,浏览速度都会比较快而且是多线程。此方法也会拒绝搜索引擎蜘蛛收录站内文件
采集对策:只能放慢采集速度,或者不采
建议:做个搜索引擎蜘蛛的IP库,只允许搜索引擎蜘蛛快速浏览站内内容。搜索引擎蜘蛛的IP库的收集,也不太容易,一个搜索引擎蜘蛛,也不一定只有一个固定的IP地址。
评论:此方法对防采集比较有效,但却会影响搜索引擎对其收录。
二、用javascript加密内容页面
弊端:此方法适用于静态页面,但会严重影响搜索引擎对其收录情况,搜索引擎收到到的内容,也都是加密后的内容
采集对策:建议不采,如非要采,就把解密码的JS脚本也采下来。
建议:目前没有好的改良建议
评论:建议指望搜索引擎带流量的站长不要使用此方法。
三、把内容页面里的特定标记替换为”特定标记+隐藏版权文字“
弊端:此方法弊端不大,仅仅会增加一点点的页面文件大小,但容易反采集
采集对策:把采集来的含有隐藏版权文字内容的版权文字替掉,或替换成自己的版权。
建议:目前没有好的改良建议
评论:自己感觉实用价值不大,就算是加上随机的隐藏文字,也等于画蛇添足。
四、只允许用户登陆后才可以浏览
弊端:此方法会严重影响搜索引擎蜘蛛对其收录
采集对策:目前落伍已经有人发了对策文章 ,具体对策就看这个吧《ASP小偷程序如何利用XMLHTTP实现表单的提交以及cookies或session的发送》
建议:目前没有好的改良建议
评论:建议指望搜索引擎带流量的站长不要使用此方法。不过此方法防一般的采集程序,还是有点效果的。
五、用javascript、vbscript脚本做分页
弊端:影响搜索引擎对其收录
采集对策:分析javascript、vbscript脚本,找出其分页规则,自己做个对应此站的分页集合页即可。
建议:目前没有好的改良建议
评论:感觉懂点脚本语言的人都能找出其分页规则
六、只允许通过本站页面连接查看,如:Request.ServerVariables("HTTP_REFERER")
弊端:影响搜索引擎对其收录
采集对策:不知道能不能模拟网页来源。。。。目前我没有对应此方法的采集对策
建议:目前没有好的改良建议
评论:建议指望搜索引擎带流量的站长不要使用此方法。不过此方法防一般的采集程序,还是有点效果的。
从以上可以看出,目前常用的防采集方法,要么会对搜索引擎收录有较大影响,要么防采集效果不好,起不到防采集的效果。那么,还有没有一种有效防采集,而又不影响搜索引擎收录的方法呢?那就请继续往下看吧,精彩的地方马上呈献给大家。
下面就是我的防采集策略,防采集而又不防搜索引擎
从前面的我讲的采集原理大家可以看出,绝大多数采集程序都是靠分析规则来进行采集的,如分析分页文件名规则、分析页面代码规则。
一、分页文件名规则防采集对策
大部分采集器都是靠分析分页文件名规则,进行批量、多页采集的。如果别人找不出你的分页文件的文件名规则,那么别人就无法对你的网站进行批量多页采集。
实现方法:
我认为用MD5加密分页文件名是一个比较好的方法,说到这里,有人会说,你用MD5加密分页文件名,别人根据此规则也可以模拟你的加密规则得到你的分页文件名。
我要指出的是我们加密分页文件名时,不要只加密文件名变化的部分
如果I代表分页的页码,那么我们不要这样加密
page_name=Md5(I,16)&".htm"
最好给要加密的页码上再跟进一个或多个字符,如:page_name=Md5(I&"任意一个或几个字母",16)&".htm"
因为MD5是无法反解密的,别人看到的会页字母是MD5加密后的结果,所以加人也无法知道你在 I 后面跟进的字母是什么,除非他用暴力****MD5,不过不太现实。
二、页面代码规则防采集对策
如果说我们的内容页面无代码规则,那么别人就无法从你的代码中提取他们所需要的一条条内容。
所以我们要的这一步做到防采集,就要使代码无规则。
实现方法:
使对方需要提取的标记随机化
1、定制多个网页模板,每个网页模板里的重要HTML标记不同,呈现页面内容时,随机选取网页模板,有的页面用CSS+DIV布局,有的页面用table布局,此方法是麻烦了点,一个内容页面,要多做几个模板页面,不过防采集本身就是一件很烦琐的事情,多做一个模板,能起到防采集的作用,对很多人来说,都是值得的。
2、如果嫌上面的方法太麻烦,把网页里的重要HTML标记随机化,也可以。
做的网页模板越多,html代码越是随机化,对方分析起内容代码时,就越麻烦,对方针对你的网站专门写采集策略时,难度就更大,在这个时候,绝大部分人,都会知难而退,因为这此人就是因为懒,才会采集别人网站数据嘛~~~再说一下,目前大部分人都是拿别人开发的采集程序去采集数据,自己开发采集程序去采集数据的人毕竟是少数。
还有些简单的思路提供给大家:
1、把对数据采集者重要,而对搜索引擎不重要的内容用客户端脚本显示
2、把一页数据,分为N个页面显示,也是加大采集难度的方法
3、用更深层的连接,因为目前大部分采集程序只能采集到网站内容的前3层,如果内容所在的连接层更深,也可以避免被采集。不过这样可能会给客户造成浏览上的不便。
如:
大多网站都是 首页----内容索引分页----内容页
如果改成:
首页----内容索引分页----内容页入口----内容页
注:内容页入口最好能加上自动转入内容页的代码
CODE:<meta http-equiv="refresh" content="6;url=内容页(http://www.xiaoqi.net)&...
其实,只要做好防采集的第一步(加密分页文件名规则),防采集的效果就已经不错了,还是建议两条反采集方法同时使用,给采集者增加采集难度,使得他们知难页退。
至此,全文完,欢迎大家在此讨论与此相关技术,谢谢!
作者:翟振恺(小琦)
关于session丢失的问题
Submitted by on 2006, August 14, 9:31 PM
*/ ---------------------------------------------------------------------------------------------------------------------
*/ 出自: 从此长大 http://www.cbcz.com
*/ 声明: 转载请注明出处.
*/ ----------------------------------------------------------------------------------------------------------------------
网站登陆两三分钟后,没有退出,session自动过期,提示没有登陆。
以前没有这样的问题,昨天开始出现,在本地测试没有问题。
我用的是虚拟空间,ASP的
不知道这里有没有谁遇到session丢失的问题。。有没有好的解决办法。。
先前找过几个win2003session丢失的解决方法..
一个是根目录下..
global.asa
代码:
<script LANGUAGE="VBScript" RUNAT="Server">
SUB Application_OnStart
session.timeout=999
END SUB
</script>
一个就是ASP代码里设置..
session.timeout=999
应该是和IIS应用程序池的设置有关 ,试试把此站点所属应用池的回收工作先取消了、或设定时间回收。
而且WEB园要是大于1的话session貌似丢失的更快..
我将TSYS的管理判断改用cookies了。
1.1的较2.0的比较好修改。
修改的文件有..
/Manage/Login.asp
/Manage/Include/Tkl_SYSProedomClass.asp
*/ 出自: 从此长大 http://www.cbcz.com
*/ 声明: 转载请注明出处.
*/ ----------------------------------------------------------------------------------------------------------------------
网站登陆两三分钟后,没有退出,session自动过期,提示没有登陆。
以前没有这样的问题,昨天开始出现,在本地测试没有问题。
我用的是虚拟空间,ASP的
不知道这里有没有谁遇到session丢失的问题。。有没有好的解决办法。。
先前找过几个win2003session丢失的解决方法..
一个是根目录下..
global.asa
代码:
<script LANGUAGE="VBScript" RUNAT="Server">
SUB Application_OnStart
session.timeout=999
END SUB
</script>
一个就是ASP代码里设置..
session.timeout=999
应该是和IIS应用程序池的设置有关 ,试试把此站点所属应用池的回收工作先取消了、或设定时间回收。
而且WEB园要是大于1的话session貌似丢失的更快..
我将TSYS的管理判断改用cookies了。
1.1的较2.0的比较好修改。
修改的文件有..
/Manage/Login.asp
/Manage/Include/Tkl_SYSProedomClass.asp
利用ASP+ASPJPEG批量为图片增加水印 边框\缩略图
Submitted by on 2006, August 14, 9:13 PM
| 代码: |
path=server.MapPath("p") "目录名,根目录则为 "/" Set Jpeg = Server.CreateObject("Persits.Jpeg") Set fso=server.CreateObject("scripting.filesystemobject") Set fo=fso.getfolder(path) for each f in fo.files Jpeg.Open path&"/"&f.name Jpeg.Height=120 "高 Jpeg.Width=120 "宽 Jpeg.Canvas.Pen.Color = &H000000 " 颜色 Jpeg.Canvas.Pen.Width = 2 "描边像素:单位pix Jpeg.Canvas.Brush.Solid = False " 如果要描边,这里不能设成"真",否则整个区域会被填充为上面的颜色 Jpeg.Canvas.Bar 1, 1, Jpeg.Width, Jpeg.Height "描边的位置及对应宽度 Jpeg.Canvas.Font.Color = &HFFFFFF " 水印颜色 Jpeg.Canvas.Font.ShadowColor = &H000000 Jpeg.Canvas.Font.Family = "宋体" "自己猜是干嘛的 Jpeg.Canvas.Font.Bold = True " 自己猜是干嘛的 Jpeg.Canvas.Font.Size = 12 "字体大小 Jpeg.Canvas.Print 60,100, "水印文字" Jpeg.Canvas.Font.ShadowXOffset=1 Jpeg.Canvas.Font.ShadowXOffset=1 Jpeg.Save path&"/s_"&f.name response.Write(f.name&" 已经处理,新生成的文件名为 s_"&f.name&"<br>") next Set fso=nothing |
ASP自定义常用函数收藏
Submitted by on 2006, August 1, 6:43 PM
"*******************************************************************
"取得IP地址
"*******************************************************************
Function Userip()
Dim GetClientIP
"如果客户端用了代理服务器,则应该用ServerVariables("HTTP_X_FORWARDED_FOR")方法
GetClientIP = Request.ServerVariables("HTTP_X_FORWARDED_FOR")
If GetClientIP = "" or isnull(GetClientIP) or isempty(GetClientIP) Then
"如果客户端没用代理,应该用Request.ServerVariables("REMOTE_ADDR")方法
GetClientIP = Request.ServerVariables("REMOTE_ADDR")
end if
Userip = GetClientIP
End function
"*******************************************************************
"转换IP地址
"*******************************************************************
function cip(sip)
tip=cstr(sip)
sip1=left(tip,cint(instr(tip,".")-1))
tip=mid(tip,cint(instr(tip,".")+1))
sip2=left(tip,cint(instr(tip,".")-1))
tip=mid(tip,cint(instr(tip,".")+1))
sip3=left(tip,cint(instr(tip,".")-1))
sip4=mid(tip,cint(instr(tip,".")+1))
cip=cint(sip1)*256*256*256+cint(sip2)*256*256+cint(sip3)*256+cint(sip4)
end function
"*******************************************************************
" 弹出对话框
"*******************************************************************
Sub alert(message)
message = replace(message,""","\"")
Response.Write ("<script>alert("" & message & "")</script>")
End Sub
"*******************************************************************
" 返回上一页,一般用在判断信息提交是否完全之后
"*******************************************************************
Sub GoBack()
Response.write ("<script>history.go(-1)</script>")
End Sub
"*******************************************************************
" 重定向另外的连接
"*******************************************************************
Sub Go(url)
Response.write ("<script>location.href("" & url & "")</script>")
End Sub
"*******************************************************************
" 我比较喜欢将以上三个结合起来使用
"*******************************************************************
Function Alert(message,gourl)
message = replace(message,""","\"")
If gourl="-1" then
Response.Write ("<script language=javascript>alert("" & message & "");history.go(-1)</script>")
Else
Response.Write ("<script language=javascript>alert("" & message & "");location="" & gourl &""</script>")
End If
Response.End()
End Function
"*******************************************************************
" 指定秒数重定向另外的连接
"*******************************************************************
sub GoPage(url,s)
s=s*1000
Response.Write "<SCRIPT LANGUAGE=JavaScript>"
Response.Write "window.setTimeout("&chr(34)&"window.navigate(""&url&"")"&chr(34)&","&s&")"
Response.Write "</script>"
end sub
"*******************************************************************
" 判断数字是否整形
"*******************************************************************
function isInteger(para)
on error resume next
dim str
dim l,i
if isNUll(para) then
isInteger=false
exit function
end if
str=cstr(para)
if trim(str)="" then
isInteger=false
exit function
end if
l=len(str)
for i=1 to l
if mid(str,i,1)>"9" or mid(str,i,1)<"0" then
isInteger=false
exit function
end if
next
isInteger=true
if err.number<>0 then err.clear
end function
"*******************************************************************
" 获得文件扩展名
"*******************************************************************
function GetExtend(filename)
dim tmp
if filename<>"" then
tmp=mid(filename,instrrev(filename,".")+1,len(filename)-instrrev(filename,"."))
tmp=LCase(tmp)
if instr(1,tmp,"asp")>0 or instr(1,tmp,"php")>0 or instr(1,tmp,"php3")>0 or instr(1,tmp,"aspx")>0 then
getextend="txt"
else
getextend=tmp
end if
else
getextend=""
end if
end function
" *----------------------------------------------------------------------------
" * 函数:CheckIn
" * 描述:检测参数是否有SQL危险字符
" * 参数:str要检测的数据
" * 返回:FALSE:安全 TRUE:不安全
" *----------------------------------------------------------------------------
function CheckIn(str)
if instr(1,str,chr(39))>0 or instr(1,str,chr(34))>0 or instr(1,str,chr(59))>0 then
CheckIn=true
else
CheckIn=false
end if
end function
" *----------------------------------------------------------------------------
" * 函数:HTMLEncode
" * 描述:过滤HTML代码
" *----------------------------------------------------------------------------
function HTMLEncode(fString)
if not isnull(fString) then
fString = replace(fString, ">", ">")
fString = replace(fString, "<", "<")
fString = Replace(fString, CHR(32), "?")
fString = Replace(fString, CHR(9), "?")
fString = Replace(fString, CHR(34), """)
fString = Replace(fString, CHR(39), """)
fString = Replace(fString, CHR(13), "")
fString = Replace(fString, CHR(10) & CHR(10), "</P><P> ")
fString = Replace(fString, CHR(10), "<BR> ")
HTMLEncode = fString
end if
end function
" *----------------------------------------------------------------------------
" * 函数:HTMLcode
" * 描述:过滤表单字符
" *----------------------------------------------------------------------------
function HTMLcode(fString)
if not isnull(fString) then
fString = Replace(fString, CHR(13), "")
fString = Replace(fString, CHR(10) & CHR(10), "</P><P>")
fString = Replace(fString, CHR(34), "")
fString = Replace(fString, CHR(10), "<BR>")
HTMLcode = fString
end if
end function
"*******************************************************************
" 弹出对话框
"*******************************************************************
Sub alert(message)
message = replace(message,""","\"")
Response.Write ("<script>alert("" & message & "")</script>")
End Sub
"*******************************************************************
" 返回上一页,一般用在判断信息提交是否完全之后
"*******************************************************************
Sub GoBack()
Response.write ("<script>history.go(-1)</script>")
End Sub
"*******************************************************************
" 重定向另外的连接
"*******************************************************************
Sub Go(url)
Response.write ("<script>location.href("" & url & "")</script>")
End Sub
"*******************************************************************
" 指定秒数重定向另外的连接
"*******************************************************************
sub GoPage(url,s)
s=s*1000
Response.Write "<SCRIPT LANGUAGE=JavaScript>"
Response.Write "window.setTimeout("&chr(34)&"window.navigate(""&url&"")"&chr(34)&","&s&")"
Response.Write "</script>"
end sub
"*******************************************************************
" * 函数:HTMLEncode
" * 描述:过滤HTML代码
"*******************************************************************
function HTMLEncode(fString)
if not isnull(fString) then
fString = replace(fString, ">", ">")
fString = replace(fString, "<", "<")
fString = Replace(fString, CHR(32), "?")
fString = Replace(fString, CHR(9), "?")
fString = Replace(fString, CHR(34), """)
fString = Replace(fString, CHR(39), """)
fString = Replace(fString, CHR(13), "")
fString = Replace(fString, CHR(10) & CHR(10), "</P><P> ")
fString = Replace(fString, CHR(10), "<BR> ")
HTMLEncode = fString
end if
end function
"*******************************************************************
"功能: 用于取代request.Form,request.QueryString
"*******************************************************************
Function SafePost(objForm)
Dim strContent
strContent = Trim(Request.Form(objForm))
strContent = Replace(strContent,"""","")
strContent = Replace(strContent,""","")
SafePost = strContent
End function
Function SafeGet(objForm)
Dim strContent
strContent = Trim(Request.QueryString(objForm))
strContent = Replace(strContent,"""","")
strContent = Replace(strContent,""","")
SafeGet = strContent
End function
"*******************************************************************
"功能: 输出程序总消耗时间
"*******************************************************************
Dim StartTime
StartTime = Timer() "存储程序开始执行时间
…………
Sub PrintExpendTime()
Response.Write("<div align=center>执行时间: " & (Timer() - StartTime) * 1000 & "毫秒 </div>")
End Sub
"取得IP地址
"*******************************************************************
Function Userip()
Dim GetClientIP
"如果客户端用了代理服务器,则应该用ServerVariables("HTTP_X_FORWARDED_FOR")方法
GetClientIP = Request.ServerVariables("HTTP_X_FORWARDED_FOR")
If GetClientIP = "" or isnull(GetClientIP) or isempty(GetClientIP) Then
"如果客户端没用代理,应该用Request.ServerVariables("REMOTE_ADDR")方法
GetClientIP = Request.ServerVariables("REMOTE_ADDR")
end if
Userip = GetClientIP
End function
"*******************************************************************
"转换IP地址
"*******************************************************************
function cip(sip)
tip=cstr(sip)
sip1=left(tip,cint(instr(tip,".")-1))
tip=mid(tip,cint(instr(tip,".")+1))
sip2=left(tip,cint(instr(tip,".")-1))
tip=mid(tip,cint(instr(tip,".")+1))
sip3=left(tip,cint(instr(tip,".")-1))
sip4=mid(tip,cint(instr(tip,".")+1))
cip=cint(sip1)*256*256*256+cint(sip2)*256*256+cint(sip3)*256+cint(sip4)
end function
"*******************************************************************
" 弹出对话框
"*******************************************************************
Sub alert(message)
message = replace(message,""","\"")
Response.Write ("<script>alert("" & message & "")</script>")
End Sub
"*******************************************************************
" 返回上一页,一般用在判断信息提交是否完全之后
"*******************************************************************
Sub GoBack()
Response.write ("<script>history.go(-1)</script>")
End Sub
"*******************************************************************
" 重定向另外的连接
"*******************************************************************
Sub Go(url)
Response.write ("<script>location.href("" & url & "")</script>")
End Sub
"*******************************************************************
" 我比较喜欢将以上三个结合起来使用
"*******************************************************************
Function Alert(message,gourl)
message = replace(message,""","\"")
If gourl="-1" then
Response.Write ("<script language=javascript>alert("" & message & "");history.go(-1)</script>")
Else
Response.Write ("<script language=javascript>alert("" & message & "");location="" & gourl &""</script>")
End If
Response.End()
End Function
"*******************************************************************
" 指定秒数重定向另外的连接
"*******************************************************************
sub GoPage(url,s)
s=s*1000
Response.Write "<SCRIPT LANGUAGE=JavaScript>"
Response.Write "window.setTimeout("&chr(34)&"window.navigate(""&url&"")"&chr(34)&","&s&")"
Response.Write "</script>"
end sub
"*******************************************************************
" 判断数字是否整形
"*******************************************************************
function isInteger(para)
on error resume next
dim str
dim l,i
if isNUll(para) then
isInteger=false
exit function
end if
str=cstr(para)
if trim(str)="" then
isInteger=false
exit function
end if
l=len(str)
for i=1 to l
if mid(str,i,1)>"9" or mid(str,i,1)<"0" then
isInteger=false
exit function
end if
next
isInteger=true
if err.number<>0 then err.clear
end function
"*******************************************************************
" 获得文件扩展名
"*******************************************************************
function GetExtend(filename)
dim tmp
if filename<>"" then
tmp=mid(filename,instrrev(filename,".")+1,len(filename)-instrrev(filename,"."))
tmp=LCase(tmp)
if instr(1,tmp,"asp")>0 or instr(1,tmp,"php")>0 or instr(1,tmp,"php3")>0 or instr(1,tmp,"aspx")>0 then
getextend="txt"
else
getextend=tmp
end if
else
getextend=""
end if
end function
" *----------------------------------------------------------------------------
" * 函数:CheckIn
" * 描述:检测参数是否有SQL危险字符
" * 参数:str要检测的数据
" * 返回:FALSE:安全 TRUE:不安全
" *----------------------------------------------------------------------------
function CheckIn(str)
if instr(1,str,chr(39))>0 or instr(1,str,chr(34))>0 or instr(1,str,chr(59))>0 then
CheckIn=true
else
CheckIn=false
end if
end function
" *----------------------------------------------------------------------------
" * 函数:HTMLEncode
" * 描述:过滤HTML代码
" *----------------------------------------------------------------------------
function HTMLEncode(fString)
if not isnull(fString) then
fString = replace(fString, ">", ">")
fString = replace(fString, "<", "<")
fString = Replace(fString, CHR(32), "?")
fString = Replace(fString, CHR(9), "?")
fString = Replace(fString, CHR(34), """)
fString = Replace(fString, CHR(39), """)
fString = Replace(fString, CHR(13), "")
fString = Replace(fString, CHR(10) & CHR(10), "</P><P> ")
fString = Replace(fString, CHR(10), "<BR> ")
HTMLEncode = fString
end if
end function
" *----------------------------------------------------------------------------
" * 函数:HTMLcode
" * 描述:过滤表单字符
" *----------------------------------------------------------------------------
function HTMLcode(fString)
if not isnull(fString) then
fString = Replace(fString, CHR(13), "")
fString = Replace(fString, CHR(10) & CHR(10), "</P><P>")
fString = Replace(fString, CHR(34), "")
fString = Replace(fString, CHR(10), "<BR>")
HTMLcode = fString
end if
end function
"*******************************************************************
" 弹出对话框
"*******************************************************************
Sub alert(message)
message = replace(message,""","\"")
Response.Write ("<script>alert("" & message & "")</script>")
End Sub
"*******************************************************************
" 返回上一页,一般用在判断信息提交是否完全之后
"*******************************************************************
Sub GoBack()
Response.write ("<script>history.go(-1)</script>")
End Sub
"*******************************************************************
" 重定向另外的连接
"*******************************************************************
Sub Go(url)
Response.write ("<script>location.href("" & url & "")</script>")
End Sub
"*******************************************************************
" 指定秒数重定向另外的连接
"*******************************************************************
sub GoPage(url,s)
s=s*1000
Response.Write "<SCRIPT LANGUAGE=JavaScript>"
Response.Write "window.setTimeout("&chr(34)&"window.navigate(""&url&"")"&chr(34)&","&s&")"
Response.Write "</script>"
end sub
"*******************************************************************
" * 函数:HTMLEncode
" * 描述:过滤HTML代码
"*******************************************************************
function HTMLEncode(fString)
if not isnull(fString) then
fString = replace(fString, ">", ">")
fString = replace(fString, "<", "<")
fString = Replace(fString, CHR(32), "?")
fString = Replace(fString, CHR(9), "?")
fString = Replace(fString, CHR(34), """)
fString = Replace(fString, CHR(39), """)
fString = Replace(fString, CHR(13), "")
fString = Replace(fString, CHR(10) & CHR(10), "</P><P> ")
fString = Replace(fString, CHR(10), "<BR> ")
HTMLEncode = fString
end if
end function
"*******************************************************************
"功能: 用于取代request.Form,request.QueryString
"*******************************************************************
Function SafePost(objForm)
Dim strContent
strContent = Trim(Request.Form(objForm))
strContent = Replace(strContent,"""","")
strContent = Replace(strContent,""","")
SafePost = strContent
End function
Function SafeGet(objForm)
Dim strContent
strContent = Trim(Request.QueryString(objForm))
strContent = Replace(strContent,"""","")
strContent = Replace(strContent,""","")
SafeGet = strContent
End function
"*******************************************************************
"功能: 输出程序总消耗时间
"*******************************************************************
Dim StartTime
StartTime = Timer() "存储程序开始执行时间
…………
Sub PrintExpendTime()
Response.Write("<div align=center>执行时间: " & (Timer() - StartTime) * 1000 & "毫秒 </div>")
End Sub
ASP自定义函数(登录,状态切换,几行几行)
Submitted by on 2006, August 1, 6:31 PM
1,经常写些系统,那么一般都是从登录程序开始,每接一个系统就写一次登录,好麻烦。
干脆直接做个登录验证函数吧,对我来说,大都情况可以胜任了:)
参数说明:
chk_regist(requestname,requestpwd,tablename,namefield,pwdfield,reurl)
requestname 为接受HTML页中输入名称的INPUT控件名
requestpwd 为接受HTML页中输入密码的INPUT控件名
tablename 为数据库中保存注册信息的表名
namefield 为该信息表中存放用户名称的字段名
pwdfield 为该信息表中存放用户密码的字段名
reurl 为登录正确后跳转的页
引用示例如下:
<%
call chk_regist("b_name","b_pwd","cn_admin","cn_name","cn_pwd","admin.asp")
%>
调试地址:http://www.cnbruce.com/tes...
2,经常有可能对某个事物进行当前状态的判断,一般即做一字段(数值类型,默认值为0)
通过对该字段值的修改达到状态切换的效果。那么,我又做了个函数,让自己轻松轻松。
参数说明:
pvouch(tablename,fildname,autoidname,indexid)
tablename 该事物所在数据库中的表名
fildname 该事物用以表明状态的字段名(字段类型是数值型)
autoidname 在该表中的自动编号名
indexid 用以修改状态的对应自动编号的值
引用示例如下:
<%
dowhat=request.QueryString("dowhat")
p_id=cint(request.QueryString("p_id"))
if dowhat="tj" and p_id<>"" then
call pvouch("cn_products","p_vouch","p_id",p_id)
end if
%>
<%if rs("p_vouch")=0 then%>
<a href=showpro.asp?dowhat=tj&p_id=<%=rs("p_id")%>>推荐</a>
<%else%>
<a href=showpro.asp?dowhat=tj&p_id=<%=rs("p_id")%>>取消推荐</a>
<%end if%>
调试地址:http://www.cnbruce.com/tes...
3,为很多中小企业写站点,一般产品展示是个大项目,那么做成的页面也就不同。
要不就是横排来几个,要不就是竖排来几个,甚至全站要翻来覆去的搞个好几次,麻烦也很累。
索性写个函数能缓解一下这种几行几列,于是就成了下面
参数说明:showpros(tablename,topnum,fildname,loopnum,typenum)
whichpro为选择何类型的产品种类
topnum表示提取多少条记录
fildname表示调试显示的字段,具体应用的时候可以省去该参数,在函数内部直接使用
loopnum表示显示的循环每行的记录条数
typenum表示循环显示的方法:目前分了两类,横向并列、纵向并列显示同一数据记录行的不同记录
引用示例如下:
<%
if request.form("submit")<>"" then
topnum=request.form("topnum")
loopnum=request.form("loopnum")
typenum=request.form("typenum")
else
topnum=8
loopnum=2
typenum=1
end if
%>
<%call showpros("cn_products",topnum,"p_name",loopnum,typenum)%>
<form action=index.asp method=post>
显示的记录总数:<input name=topnum value=<%=topnum%>>
显示的行循环数:<input name=loopnum value=<%=loopnum%>>
显示的方式类型:<select name=typenum>
<option value="1">方式1</option>
<option value="2">方式2</option>
</select>
<input type=submit name=submit value=Sure>
</form>
干脆直接做个登录验证函数吧,对我来说,大都情况可以胜任了:)
| 代码: |
| <%
Function chk_regist(requestname,requestpwd,tablename,namefield,pwdfield,reurl) dim cn_name,cn_pwd cn_name=trim(request.form(""&requestname&"")) cn_pwd=trim(request.form(""&requestpwd&"")) if cn_name="" or cn_pwd="" then response.Write("<script language=javascript>alert(""请将帐号密码填写完整,谢谢合作。"");history.go(-1)</script>") end if Set rs = Server.CreateObject ("ADODB.Recordset") sql = "Select * from "&tablename&" where "&namefield&"=""&cn_name&""" rs.open sql,conn,1,1 if rs.eof then response.Write("<script language=javascript>alert(""没有该会员ID,请确认有没有被申请。"");history.go(-1)</script>") else if rs(""&pwdfield&"")=cn_pwd then session("cn_name")=rs(""&namefield&"") response.Redirect(reurl) else response.Write("<script language=javascript>alert(""提醒,您的帐号和密码是不吻合。注意数字和大小写。"");history.go(-1)</script>") end if end if rs.close Set rs = Nothing End Function %> |
参数说明:
chk_regist(requestname,requestpwd,tablename,namefield,pwdfield,reurl)
requestname 为接受HTML页中输入名称的INPUT控件名
requestpwd 为接受HTML页中输入密码的INPUT控件名
tablename 为数据库中保存注册信息的表名
namefield 为该信息表中存放用户名称的字段名
pwdfield 为该信息表中存放用户密码的字段名
reurl 为登录正确后跳转的页
引用示例如下:
<%
call chk_regist("b_name","b_pwd","cn_admin","cn_name","cn_pwd","admin.asp")
%>
调试地址:http://www.cnbruce.com/tes...
2,经常有可能对某个事物进行当前状态的判断,一般即做一字段(数值类型,默认值为0)
通过对该字段值的修改达到状态切换的效果。那么,我又做了个函数,让自己轻松轻松。
| 代码: |
| <%
Function pvouch(tablename,fildname,autoidname,indexid) dim fildvalue Set rs = Server.CreateObject ("ADODB.Recordset") sql = "Select * from "&tablename&" where "&autoidname&"="&indexid rs.Open sql,conn,2,3 fildvalue=rs(""&fildname&"") if fildvalue=0 then fildvalue=1 else fildvalue=0 end if rs(""&fildname&"")=fildvalue rs.update rs.close Set rs = Nothing End Function %> |
参数说明:
pvouch(tablename,fildname,autoidname,indexid)
tablename 该事物所在数据库中的表名
fildname 该事物用以表明状态的字段名(字段类型是数值型)
autoidname 在该表中的自动编号名
indexid 用以修改状态的对应自动编号的值
引用示例如下:
<%
dowhat=request.QueryString("dowhat")
p_id=cint(request.QueryString("p_id"))
if dowhat="tj" and p_id<>"" then
call pvouch("cn_products","p_vouch","p_id",p_id)
end if
%>
<%if rs("p_vouch")=0 then%>
<a href=showpro.asp?dowhat=tj&p_id=<%=rs("p_id")%>>推荐</a>
<%else%>
<a href=showpro.asp?dowhat=tj&p_id=<%=rs("p_id")%>>取消推荐</a>
<%end if%>
调试地址:http://www.cnbruce.com/tes...
3,为很多中小企业写站点,一般产品展示是个大项目,那么做成的页面也就不同。
要不就是横排来几个,要不就是竖排来几个,甚至全站要翻来覆去的搞个好几次,麻烦也很累。
索性写个函数能缓解一下这种几行几列,于是就成了下面
| 代码: |
| <%
function showpros(tablename,topnum,fildname,loopnum,typenum) Set rs = Server.CreateObject ("ADODB.Recordset") sql = "Select top "&topnum&" * from "&tablename rs.Open sql,conn,1,1 if rs.eof and rs.bof then response.Write("暂时无该记录") else response.Write("<table width="100%">") for i=1 to rs.recordcount if (i mod loopnum=1) then response.write"<tr>" end if select case typenum case "1" response.Write("<td><table width="100%"><tr><td bgcolor=red width="50%">") response.Write(rs(""&fildname&"")) response.Write("</td><td bgcolor=black>") response.Write("方式1之"&i&"记录")"此处的“方式1”可以替换显示为其余字段的值 response.Write("</td></tr>")"如果字段比较多,继续添加新个表格行来显示 response.Write("</table></td>") case "2" response.Write("<td><table width="100%"><tr><td bgcolor=red>") response.Write(rs(""&fildname&"")) response.Write("</td></tr>") response.Write("<tr><td bgcolor=black>") response.Write("方式2之"&i&"记录") response.Write("</td></tr>") response.Write("</table></td>") end select if (i mod loopnum=0) then response.write"</tr>" end if rs.movenext next response.Write("</table>") end if rs.close Set rs = Nothing end function %> |
参数说明:showpros(tablename,topnum,fildname,loopnum,typenum)
whichpro为选择何类型的产品种类
topnum表示提取多少条记录
fildname表示调试显示的字段,具体应用的时候可以省去该参数,在函数内部直接使用
loopnum表示显示的循环每行的记录条数
typenum表示循环显示的方法:目前分了两类,横向并列、纵向并列显示同一数据记录行的不同记录
引用示例如下:
<%
if request.form("submit")<>"" then
topnum=request.form("topnum")
loopnum=request.form("loopnum")
typenum=request.form("typenum")
else
topnum=8
loopnum=2
typenum=1
end if
%>
<%call showpros("cn_products",topnum,"p_name",loopnum,typenum)%>
<form action=index.asp method=post>
显示的记录总数:<input name=topnum value=<%=topnum%>>
显示的行循环数:<input name=loopnum value=<%=loopnum%>>
显示的方式类型:<select name=typenum>
<option value="1">方式1</option>
<option value="2">方式2</option>
</select>
<input type=submit name=submit value=Sure>
</form>
ASP有用的代码速查
Submitted by on 2006, August 1, 7:44 AM
1、数据库连接。
ASP与Access数据库连接:
<%@ language=VBs cript%>
<%
dim conn,mdbfile
mdbfile=server.mappath("数据库名称.mdb")
set conn=server.createobject("adodb.connection")
conn.open "driver={microsoft access driver (*.mdb)};uid=admin;pwd=数据库密码;dbq="&mdbfile
%>
ASP与SQL数据库连接:
<%@ language=VBs cript%>
<%
dim conn
set conn=server.createobject("ADODB.connection")
con.open "PROVIDER=SQLOLEDB;DATA SOURCE=SQL服务器名称或IP地址;UID=sa;PWD=数据库密码;DATABASE=数据库名称
%>
DW中用字符串连接代码:
"Driver={Microsoft Access Driver (*.mdb)};DBQ=数据库的绝对路径"
等做完后再打开数据库服务器,把
"Driver={Microsoft Access Driver (*.mdb)};DBQ=数据库的绝对路径"
换成
"Provider=Microsoft.Jet.OLEDB.4.0;data source="& server.mappath("服务器根目录下所在数据库路径")
并把本地服务器修改成测试服务器
2、加载别的页面。
<!--#include file = "页面的路径和名称"-->
3、显示数据库中的数据。
<%=rs("字段")%>
4、输出。
Response.Write("文字或者字符串");
5、打开数据库并建立数据集对象。
set conn=server.CreateObject("ADODB.connection")
conn.open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source="&server.MapPath("***/photodata.mdb") 更改您的数据库文件存放路径
set rs=server.createobject("ADODB.recordset") 建立数据集
sql="Select * FROM data" 更改您的数据库表名
rs.Open sql,conn,1,1
6、获得系统的时间。
<%=now()%>
7、取得来访问的IP。
<%=request.serverVariables("remote_host")%>
8、随机数。
<%randomize%>
<%=(int(rnd()*n)+1)%>
N为可改变数
9、跳转页面。
Response.Redirect("页面")
10、弹出消息框。
Response.Write("<script>alert(消息框!)</script>")
11、用hidden类型来传递变量。
< % form method="post" action="mynextpage.asp" >
< % for each item in request.form % >
< input namee="< %=item% >" type="HIDDEN"
value="< %=server.HTMLEncode(Request.form(item)) % >" >
< % next % >
< /form >
12、常用SQL语句整理。
(1) 数据记录筛选:
sql="select * from 数据表 where 字段名=字段值 order by 字段名 [desc]"
sql="select * from 数据表 where 字段名 like %字段值% order by 字段名 [desc]"
sql="select top 10 * from 数据表 where 字段名 order by 字段名 [desc]"
sql="select * from 数据表 where 字段名 in (值1,值2,值3)"
sql="select * from 数据表 where 字段名 between 值1 and 值2"
(2) 更新数据记录:
sql="update 数据表 set 字段名=字段值 where 条件表达式"
sql="update 数据表 set 字段1=值1,字段2=值2 …… 字段n=值n where 条件表达式"
(3) 删除数据记录:
sql="delete from 数据表 where 条件表达式"
sql="delete from 数据表" (将数据表所有记录删除)
(4) 添加数据记录:
sql="insert into 数据表 (字段1,字段2,字段3 …) valuess (值1,值2,值3 …)"
sql="insert into 目标数据表 select * from 源数据表" (把源数据表的记录添加到目标数据表)
(5) 数据记录统计函数:
AVG(字段名) 得出一个表格栏平均值
COUNT(*|字段名) 对数据行数的统计或对某一栏有值的数据行数统计
MAX(字段名) 取得一个表格栏最大的值
MIN(字段名) 取得一个表格栏最小的值
SUM(字段名) 把数据栏的值相加
引用以上函数的方法:
sql="select sum(字段名) as 别名 from 数据表 where 条件表达式"
set rs=conn.excute(sql)
用 rs("别名") 获取统的计值,其它函数运用同上。
(5) 数据表的建立和删除:
Create TABLE 数据表名称(字段1 类型1(长度),字段2 类型2(长度) …… )
例:Create TABLE tab01(name varchar(50),datetime default now())
Drop TABLE 数据表名称 (永久性删除一个数据表)
ASP与Access数据库连接:
<%@ language=VBs cript%>
<%
dim conn,mdbfile
mdbfile=server.mappath("数据库名称.mdb")
set conn=server.createobject("adodb.connection")
conn.open "driver={microsoft access driver (*.mdb)};uid=admin;pwd=数据库密码;dbq="&mdbfile
%>
ASP与SQL数据库连接:
<%@ language=VBs cript%>
<%
dim conn
set conn=server.createobject("ADODB.connection")
con.open "PROVIDER=SQLOLEDB;DATA SOURCE=SQL服务器名称或IP地址;UID=sa;PWD=数据库密码;DATABASE=数据库名称
%>
DW中用字符串连接代码:
"Driver={Microsoft Access Driver (*.mdb)};DBQ=数据库的绝对路径"
等做完后再打开数据库服务器,把
"Driver={Microsoft Access Driver (*.mdb)};DBQ=数据库的绝对路径"
换成
"Provider=Microsoft.Jet.OLEDB.4.0;data source="& server.mappath("服务器根目录下所在数据库路径")
并把本地服务器修改成测试服务器
2、加载别的页面。
<!--#include file = "页面的路径和名称"-->
3、显示数据库中的数据。
<%=rs("字段")%>
4、输出。
Response.Write("文字或者字符串");
5、打开数据库并建立数据集对象。
set conn=server.CreateObject("ADODB.connection")
conn.open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source="&server.MapPath("***/photodata.mdb") 更改您的数据库文件存放路径
set rs=server.createobject("ADODB.recordset") 建立数据集
sql="Select * FROM data" 更改您的数据库表名
rs.Open sql,conn,1,1
6、获得系统的时间。
<%=now()%>
7、取得来访问的IP。
<%=request.serverVariables("remote_host")%>
8、随机数。
<%randomize%>
<%=(int(rnd()*n)+1)%>
N为可改变数
9、跳转页面。
Response.Redirect("页面")
10、弹出消息框。
Response.Write("<script>alert(消息框!)</script>")
11、用hidden类型来传递变量。
< % form method="post" action="mynextpage.asp" >
< % for each item in request.form % >
< input namee="< %=item% >" type="HIDDEN"
value="< %=server.HTMLEncode(Request.form(item)) % >" >
< % next % >
< /form >
12、常用SQL语句整理。
(1) 数据记录筛选:
sql="select * from 数据表 where 字段名=字段值 order by 字段名 [desc]"
sql="select * from 数据表 where 字段名 like %字段值% order by 字段名 [desc]"
sql="select top 10 * from 数据表 where 字段名 order by 字段名 [desc]"
sql="select * from 数据表 where 字段名 in (值1,值2,值3)"
sql="select * from 数据表 where 字段名 between 值1 and 值2"
(2) 更新数据记录:
sql="update 数据表 set 字段名=字段值 where 条件表达式"
sql="update 数据表 set 字段1=值1,字段2=值2 …… 字段n=值n where 条件表达式"
(3) 删除数据记录:
sql="delete from 数据表 where 条件表达式"
sql="delete from 数据表" (将数据表所有记录删除)
(4) 添加数据记录:
sql="insert into 数据表 (字段1,字段2,字段3 …) valuess (值1,值2,值3 …)"
sql="insert into 目标数据表 select * from 源数据表" (把源数据表的记录添加到目标数据表)
(5) 数据记录统计函数:
AVG(字段名) 得出一个表格栏平均值
COUNT(*|字段名) 对数据行数的统计或对某一栏有值的数据行数统计
MAX(字段名) 取得一个表格栏最大的值
MIN(字段名) 取得一个表格栏最小的值
SUM(字段名) 把数据栏的值相加
引用以上函数的方法:
sql="select sum(字段名) as 别名 from 数据表 where 条件表达式"
set rs=conn.excute(sql)
用 rs("别名") 获取统的计值,其它函数运用同上。
(5) 数据表的建立和删除:
Create TABLE 数据表名称(字段1 类型1(长度),字段2 类型2(长度) …… )
例:Create TABLE tab01(name varchar(50),datetime default now())
Drop TABLE 数据表名称 (永久性删除一个数据表)
生成固定大小的缩略图几法
Submitted by on 2006, August 1, 7:25 AM
| 代码: |
| <HTML> <HEAD> <TITLE>演示图片等比例缩小</TITLE> <script> function Wa_SetImgAutoSize() { var img=document.all.img1;//获取图片 var MaxWidth=160;//设置图片宽度界限 var MaxHeight=120;//设置图片高度界限 var HeightWidth=img.offsetHeight/img.offsetWidth;//设置高宽比 var WidthHeight=img.offsetWidth/img.offsetHeight;//设置宽高比 if(img.readyState!="complete")return false;//确保图片完全加载 if(img.offsetWidth>MaxWidth){ img.width=MaxWidth; img.height=MaxWidth*HeightWidth; } if(img.offsetHeight>MaxHeight){ img.height=MaxHeight; img.width=MaxHeight*WidthHeight; } } </script> </HEAD> <BODY> <img src="52.jpg" border=0 id="img1" onload="Wa_SetImgAutoSize();"> <br> </BODY> </HTML> |
此为前台js调用的
后台使用asp.jpeg组件 根据比例缩放,(不裁减)缩小为小于160*160的
然后用其均匀覆盖在160*160的背景图上(使用jpeg组件水印功能)
| 代码: |
| Function pic(picname) Set Jpeg = Server.CreateObject("Persits.Jpeg") Jpeg.Open Server.MapPath(PicName) 'response.Write Server.MapPath(PicName) 'response.end d=jpeg.OriginalWidth*1.25 if Jpeg.OriginalHeight>d then 'a=(Jpeg.OriginalHeight-d)/5 'b=Jpeg.OriginalHeight-a jpeg.crop 0,0,Jpeg.Originalwidth,d Jpeg.Save Server.MapPath(PicName) end if dd=jpeg.OriginalHeight*0.75 if Jpeg.OriginalHeight<d then aa=(Jpeg.OriginalWidth-dd)/2 bb=Jpeg.OriginalWidth-aa jpeg.crop aa,0,bb,Jpeg.OriginalHeight Jpeg.Save Server.MapPath(picname) end if set jpeg=nothing set logo=nothing daxiao (PicName) waterMark (picname) End Function Function daxiao(PicName) Set Jpeg = Server.CreateObject("Persits.Jpeg") Jpeg.Open Server.MapPath(PicName) Jpeg.Width =240 Jpeg.Height = 320 Jpeg.Save Server.MapPath(picName) set jpeg=nothing set logo=nothing End Function Function WaterMark(PicName) Set Jpeg = Server.CreateObject("Persits.Jpeg") Jpeg.Open Server.MapPath(PicName) Jpeg.Canvas.Font.Color = &HFFffff Jpeg.Canvas.Font.Family = "宋体" Jpeg.Canvas.Font.Bold = false jpeg.Canvas.Font.Size = 13 Jpeg.Canvas.Print Jpeg.OriginalWidth-80, Jpeg.OriginalHeight-20, "mnv520.com" Jpeg.Save Server.MapPath(PicName) set jpeg=nothing set logo=nothing End Function |