分类:
2008-11-11 17:42:51
首先探讨下URL问题。RFC1738对Uniform Resource Locators (URL)进行了详细的说明。
URL通常写成:
<方案>:<方案描述部分>
<方案>由"a"-"z", "+", ".", "-"组成,程序解释应该是非大小写敏感的。URL方案保留了一些字符并赋予特定的含义,保留字符有;","/", "?", ":", "@", "=" 和 "&"。
通常的URL具体组成是:
<方案>//<用户名>:<密码>@<主机>:<端口>/
这个URL中"<用户名>:<密码>@", "<端口>:", "/
spider通常要抓取的主要是HTTP协议的信息,所以再看看HTTP协议的URL:
>:
列一下URL方案(只列HTTP, FILE, FTP的吧)的BNF吧,写程序的时候看此BNF更清晰一些。
genericurl = scheme ":" schemepart ;特定的预定义方案在这里进行定义;新方案可以在IANA那儿注册 url = httpurl | ftpurl | newsurl | nntpurl | telneturl | gopherurl | waisurl | mailtourl | fileurl | prosperourl | otherurl ;新方案遵从一般语法 otherurl = genericurl ;方案都是小写的;解释程序应该忽略大小写 scheme = 1*[ lowalpha | digit | "+" | "-" | "." ] schemepart = *xchar | ip-schemepart ;基于协议的ip的URL方案部分: ip-schemepart = "//" login [ "/" urlpath ] login = [ user [ ":" password ] "@" ] hostport hostport = host [ ":" port ] host = hostname | hostnumber hostname = *[ domainlabel "." ] toplabel domainlabel = alphadigit | alphadigit *[ alphadigit | "-" ] alphadigit toplabel = alpha | alpha *[ alphadigit | "-" ] alphadigit alphadigit = alpha | digit hostnumber = digits "." digits "." digits "." digits port = digits user = *[ uchar | ";" | "?" | "&" | "=" ] password = *[ uchar | ";" | "?" | "&" | "=" ] urlpath = *xchar ;FTP(文件传输协议,请参考RFC959) ftpurl = "ftp://" login [ "/" fpath [ ";type=" ftptype ]] fpath = fsegment *[ "/" fsegment ] fsegment = *[ uchar | "?" | ":" | "@" | "&" | "=" ] ftptype = "A" | "I" | "D" | "a" | "i" | "d" ;FILE(文件) fileurl = "file://" [ host | "localhost" ] "/" fpath ;HTTP(超文本传输协议) httpurl = "http://" hostport [ "/" hpath [ "?" search ]] hpath = hsegment *[ "/" hsegment ] hsegment = *[ uchar | ";" | ":" | "@" | "&" | "=" ] search = *[ uchar | ";" | ":" | "@" | "&" | "=" ] |
spider的入口就是URL,它是一个客户端,要用scheme, host和port去连接服务器,然后使用username, password去验证身份,再使用协议中定义的方法去下载url中的文件。很明显要去URL进行分析,把URL分解成单元,在每一个过程中去使用不同的单元来完成相应的事情,最终的结果是完成一次正确的数据请求,url的长度并没有在RFC 1738中说明,然而一般来说,512个字符完全可以了,好像IE中最大是2000?差不多是这个数字吧。
一但涉及到字符串,效率从来就是放在桌面上必谈的东西,其实分析URL是很简单的东西,完全可以用正则表达式,我们这里写个URL类,专门用来分析URL,分解成各个部分,数据结构当然用string了,这个够方便简单,string::find(...)对字符串的查找效率虽低,可是分析URL一般查找是单个字符,只能是O(n)的时间复杂度,所以完全OK。