当前位置: 首页 > 图文教程 > 网络编程 > ASP > 用xmlhttp编写web采集程序

ASP
一个ASP版的图片浏览管理器
无组件上传图片至SQLSERVER数据库
利用Jmail.Message发送邮件
用Web页面执行客户端程序
多图片上传到指定的目录并存到数据库
dreamweaverMX通用分页代码研究
下拉菜单输入,根据输入内容自动定位
中文的无组件文件上传ASP函数
一个利用adsi得到局域网信息的asp文件
根据需要动态include不同的文件
让自定义文件下载支持断点续传
用数组实现数据记录的批量录入方法
上传的进度条 实时反映上传情况
用ASP动态生成javascript的表单验证代码
ASP 编程中20个非常有用的例子
ASP生成Word文档的又一方法
用asp解析图片地址,并将其保存。
利用ASP的文件操作实现用户管理
创建 Visual Basic COM 组件在 ASP 中使用
调试 ASP 中使用的 Visual Basic COM 组件

ASP 中的 用xmlhttp编写web采集程序


出处:互联网   整理: 软晨网(RuanChen.com)   发布: 2009-10-12   浏览: 82 ::
收藏到网摘: n/a

晰带语法着色的版本:http://gwx.showus.net/blog/article.asp?id=229
原创很辛苦,转载请注明原文链接:http://gwx.showus.net/blog/article.asp?id=229
web采集程序?网页抓取程序?小倫程序?不管怎么叫,这种程序应用倒是蛮广的。本文不讨论这种使用这种程序引起的版权或道德问题,只谈这种程序在ASP+VBScript环境下的实现 :-)
预备知识:除了一般的ASP+VBScript的知识外,你还需要了解xmlhttp对象和正则表达式对象。xmlhttp对象是时下风头正劲的Ajax的主角;而学好了正则表达式,你再也不用为处理复杂的字符串犯愁。
在编写和调试正则表达式时,RegEx 这个小工具非常有用。
目录
抓取一个远程网页并保存到本地
改进:处理乱码
同时下载远程网页的图片(和其它文件)
改进:探测真实URL
改进:避免重复下载
实战举例(以****为例)
分析列表页
内容页的技巧
分析内容页中的上一页,下一页
高级主题:UTF-8和GB2312的转换
更多高级主题:登陆后抓取,客户端伪造
己有的采集程序
原文链接:http://gwx.showus.net/blog/article.asp?id=229
1.抓取一个远程网页并保存到本地
'用于调试的过程,后面会多次调用检查中间结果
Dim inDebug:inDebug=True
Sub D(Str)
If inDebug = False Then Exit Sub
Response.Write("<div style='color:#003399; border: solid 1px #003399; background: #EEF7FF; margin: 1px; font-size: 12px; padding: 4px;'>")
Response.Write(Str &"</div>")
Response.Flush()
End Sub
'过程: Save2File
'功能: 把文本或字节流保存为文件
'参数: sContent 要保存的内容
' sFile 保存到文件,形如"files/abc.htm"
' bText 是否是文本
' bOverWrite 是否覆盖己存在文件
Sub Save2File(sContent,sFile,bText,bOverWrite)
Call D("Save2File:"+sFile+" *是否文本:"&bText)
Dim SaveOption,TypeOption
If (bOverWrite = True) Then SaveOption=2 Else SaveOption=1
If (bText = True) Then TypeOption=2 Else TypeOption=1
Set Ads = Server.CreateObject("Adodb.Stream")
With Ads
.Type = TypeOption
.Open
If (bText = True) Then .WriteText sContent Else .Write sContent
.SaveToFile Server.MapPath(sFile),SaveOption
.Cancel()
.Close()
End With
Set Ads=nothing
End Sub
关键的函数
'函数: myHttpGet
'功能: 抓取一个远程文件(网页或图片等)并保存到本地
'参数: sUrl 远程文件的URL
' bText 是否是文本(网页),下载远程图片是bText=False
'返回: 抓取的内容
Function myHttpGet(sUrl,bText)
Call D("<font color=red>myHttpGet:</font>"+sUrl+" *是否文本:"&bText)
'Set oXml = Server.CreateObject("Microsoft.XMLHTTP")
Set oXml = Server.CreateObject("MSXML2.ServerXMLHTTP") '服务器版本的XMLHTTP组件
'理解下面的内容,你可以参考一下MSDN中的MSXML2.ServerXMLHTTP
With oXml
.Open "GET",sUrl,False
.Send
While .readyState <> 4 '等待下载完毕
.waitForResponse 1000
Wend
If bText = True Then
myHttpGet = bytes2BSTR(.responseBody)
Else
myHttpGet = .responseBody
End If
End With
Set oXml = Nothing
End Function
改进:处理乱码
直接读取服务器返回的中文内容会出现乱码,myHttpGet函数中引用的bytes2BSTR的作用是正确读取服务器返回的文件中的双字节文本(比如说中文)
'myHttpGet helper 处理双字节文本
Function bytes2BSTR(vIn)
strReturn = ""
For i = 1 To LenB(vIn)
ThisCharCode = AscB(MidB(vIn,i,1))
If ThisCharCode < &H80 Then
strReturn = strReturn & Chr(ThisCharCode)
Else
NextCharCode = AscB(MidB(vIn,i+1,1))
strReturn = strReturn & Chr(CLng(ThisCharCode) * &H100 + CInt(NextCharCode))
i = i + 1
End If
Next
bytes2BSTR = strReturn
End Function
bytes2BSTR函数的功能也可以利用Adodb.Stream组件通过下面的函数实现,虽然下面的函数可以指定字符集Charset,但它并不能转换编码,即传递"UTF-8"给参数sCset,来读取一张GB2312编码的网页将显示为乱码。
'CharsetHelper可以正确的读取以sCset(如"GB2312","UTF-8"等)编码的文件
Function CharsetHelper(arrBytes,sCset)
Call D("CharsetHelper: "+sCset)
Dim oAdos
Set oAdos = CreateObject("Adodb.Stream")
With oAdos
.Type = 1
.Mode =3 'adModeReadWrite
.Open
.Write arrBytes
.Position = 0
.Type = 2
.Charset = sCset
CharsetHelper = .ReadText
.Close
End With
Set oAdos = Nothing
End Function
2.同时下载远程网页的图片(和其它文件)
'函数: ProcessRemoteUrl
'功能: 替换字符串中的远程文件为本地文件并保存远程文件
'参数: strContent 要替换的字符串,即远程网页文件的内容
' sSavePath 不以/结尾的相对路径,指示远程文件的本地保存路径
' sPreceding 更改后的URL前缀,如http://somehost/upload/
'返回: 替换远程路径为本地路径之后的新的网页文本内容
Function ProcessRemoteUrl(sContent,sSavePath,sPreceding)
Call D("ProcessRemoteUrl")
Set re=new RegExp
re.IgnoreCase =true
re.Global=True
'下面的正则中.SubMatches(4)=文件名全名.SubMatches(5)文件扩展名
re.Pattern = "((http):(?:\/\/){1}(?:(?:\w)+[.])+(net|com|cn|org|cc|tv|[0-9]{1,4})(\S*\/)((?:\S)+[.]{1}(gif|jpg|jpeg|png|bmp)))"
Set RemoteFile = re.Execute(sContent)
Dim SaveFileName
'RemoteFile 正则表达式Match对象的集合
'RemoteFileUrl 正则表达式Match对象
For Each RemoteFileUrl in RemoteFile
SaveFileName = RemoteFileUrl.SubMatches(4)
Call Save2File(myHttpGet(RemoteFileUrl,False),sSavePath&"/"&SaveFileName,False,True)
sContent=Replace(sContent,RemoteFileUrl,sPreceding&SaveFileName)
Next
ProcessRemoteUrl=sContent
End Function
改进:探测真实URL
上面的ProcessRemoteUrl函数不能正确处理形如<img src="/upload/tech/20091012/20091012011931_6bc24fc1ab650b25b4114e93a98f1eb/upload/tech/20091012/20091012011932_fa7cdfad1a5aaf8370ebeda47a1ff1c3.jpg" />和<a href="/upload/tech/20091012/20091012011931_9e3cfc48eccf81a0d57663e129aef3cb.gif" ...的内容,要处理这些相对链接,我们可以先用下面的函数把网页中的相对链接都转换成绝对链接
'函数: DetectUrl
'功能: 替换字符串中的远程文件相对路径为以http://..开头的绝对路径
'参数: sContent 要处理的含相对路径的网页的文本内容
' sUrl 所处理的远程网页自身的URL,用于分析相对路径
'返回: 替换相对链接为绝对链接之后的新的网页文本内容
Function DetectUrl(sContent,sUrl)
Call D("DetectUrl:"&sUrl)
'分析URL
Dim re,sMatch
Set re=new RegExp
re.Multiline=True
re.IgnoreCase =true
re.Global=True
re.Pattern = "(http://[-A-Z0-9.]+)/[-A-Z0-9+&@#%~_|!:,.;/]+/"
Dim sHost,sPath
'http://localhost/get/sample.asp
Set sMatch=re.Execute(sUrl)
'http://localhost
sHost=sMatch(0).SubMatches(0)
'http://localhost/get/
sPath=sMatch(0)
re.Pattern = "(src|href)=""?((?!http://)[-A-Z0-9+&@#%=~_|!:,.;/]+)""?"
Set RemoteFile = re.Execute(sContent)
'RemoteFile 正则表达式Match对象的集合
'RemoteFileUrl 正则表达式Match对象,形如src="/upload/tech/20091012/20091012011932_aeb3135b436aa55373822c010763dd54.jpg"
Dim sAbsoluteUrl
For Each RemoteFileUrl in RemoteFile
'<img src="/upload/tech/20091012/20091012011932_fa7cdfad1a5aaf8370ebeda47a1ff1c3.jpg">,<img src="f//upload/tech/20091012/20091012011932_fa7cdfad1a5aaf8370ebeda47a1ff1c3.jpg">,<img src="/ff//upload/tech/20091012/20091012011932_fa7cdfad1a5aaf8370ebeda47a1ff1c3.jpg">
If Left(RemoteFileUrl.SubMatches(1),1)="/" Then
sAbsoluteUrl=sHost
Else
sAbsoluteUrl=sPath
End If
sAbsoluteUrl = RemoteFileUrl.SubMatches(0)&"="""&sAbsoluteUrl&RemoteFileUrl.SubMatches(1)&""""
sContent=Replace(sContent,RemoteFileUrl,sAbsoluteUrl)
Next
DetectUrl=sContent
End Function
改进:避免重复下载
网页中的有些图片,比如spacer.gif重复出现,会被重复下载,壁免这个问题的一个方法是设置一个arrUrls数组,把采集过的文件的URL放在里面,在每次采集前先遍历数组看是否已经采集,然后只参集没有参集过的文件
3.实战举例(以****为例)
****是我最经常去的地方,而且网速不错,就以她为例啦,没有恶意哦:-)
分析列表页
内容页的技巧
分析内容页中的上一页,下一页
想了一下,这部分内容还是晢时不写,免得被BS了 :-),还省得打好多字。 无非是把远程网页采集下来,然后用正则表达式分析提取其中的特定内容,如标题,作者,内容之类的 我有两个小小的经验:
一是网页源码前后的内容对分析有很大的干扰,你可以用下面的方法先把它支除
'抽取部分内容进行分析,你可以用用EditPlus数字数
'去除前7600和后5000的字符
sPageW=Left(sPageW,Len(sPageW)-5000)
sPageW=Mid(sPageW,7600)
二是你可能不想在对方的服务器上留下连续的浏览记录,下面的一个小函数会有所帮助
'过程: Sleep
'功能: 程序在此晢停几秒
'参数: iSeconds 要暂停的秒数
Sub Sleep(iSeconds)
D Timer()&" <font color=blue>Sleep For "&iSeconds&" Seconds</font>"
Dim t:t=Timer()
While(Timer()<t+iSeconds)
'Do Nothing
Wend
D Timer()&" <font color=blue>Sleep For "&iSeconds&" Seconds OK</font>"
End Sub
'调用举例,晢停,时长随机,在3秒以内
Sleep(Fix(Rnd()*3))
三就是多用正则表达式测试工具提高编写正则表达式的效率
4.高级主题:UTF-8和GB2312的转换
这个问题比较复杂,由于我智力和精力方面的原因没有完全搞定,网上己有的资料也大多不完全正确或者不全面,我推荐一个UTF-8和GB2312的转换的C语言的实现供大家参考,它功能完整而且不依赖Windows API函数。
我在试着用ASP+VBScript实现它,有一些不太成熟的经验:
计算机上的文件、操作系统内部的字符串表示都是Unicode的,所以,UTF-8和GB2312之间的转换需要以Unicode为中介
UTF-8就是Unicode的一个变体,它们之间的相互转换比较简单,参考下图就可以了
GB2312和Unicode的编码好像是不相关的,不依赖操作系统内部函数进行转换就需要一个编码映射表,指出GB2312和Unicode的编码一一对应的关系,这个编码表大约包含7480×2个项目。
在ASP文件中,要默认以某和编码(如GB2312)读取一个字符串,需要将ASP的CodePage设为相应代码页(对GB2312是CodePage=936)
编码转换中还有一些又小又重要的问题我还不知道:-(
5.更多高级主题:登陆后抓取,客户端伪造等
xmlhttp对象可以以post或get的方法与http服务器交互,可以设置和读取http头,学习一下http协议,并且更深入的了解一些xmlhttp对象的方法和属性,你就可以用它来模拟一个浏览器,自动的做各种以前需要人来做的重复工作。
6.己有的采集程序
本文旨在讨论采集程序在ASP+VBScript环境下的实现,如果你需要一个网页采集程序,下面的链接可能对你有用。
LocoySpider火车头网页内容采集器
C#+.Net编写的内容采集器,它的一个重要特点是不将采集来的内容保存到数据库,而是使用自定的POST提交的别的网页,如内容管理系统的新建内容页。免费。
BeeCollector (小蜜蜂采集器)
PHP+MySQL编写的内容采集器。
风讯内容管理系统
这个强大的内容管理系统内带有一个ASP的网页内容采集器