johnson.lee 发表于 2013-1-15 02:44:13

网络爬虫-如何将相对路径转为绝对路径

最近在写一个蜘蛛程序,碰到了一个问题,就是如何将页面内超链接的相对路径转为绝对路径,Google了一遍,有很多例子,看了一下,全是不太正确的做法,考虑太片面了,它们的做法大致是这样:
如当前页面是:http://localhost:5995/web/index.html
代码如下:
String url = "http://localhost:5995/web/index.html";int offset = url.lastIndexOf("/");String cate = url.substring(0, 0ffset + 1);String absPath = cate + "页面内的相对路径";
上面的代码只是在当前请求的路径不是服务器端的目录时适用,有些站点没有屏蔽对目录的访问,就拿上面的url做例子,当前站点的目录结构如下:
web
├─images
│├─logo.gif
│├─bg.gif
│├─banner.swf
│└─style.css
├─scripts
│├─swfobject.js
│├─common.js
│└─AjaxRequest.js
└─upload
    ├─201001090001.rar
    ├─201001090002.rar
    ├─201001090003.rar
    ├─201001090004.rar
    └─201001090005.rar
假设此站点没有屏蔽对目录的访问,那么在浏览器上请求http://localhost:5995/web/scripts,查看源代码:
目录清单 -- /web/scripts/ -------------------------------------------------------------------------------- Wednesday, December 16, 2009 12:48 PM      8,670 swfobject.js    Monday, December 07, 2009 05:09 PM      1,450 common.jsThursday, December 31, 2009 01:54 PM      3,309 AjaxRequest.js--------------------------------------------------------------------------------版本信息: ASP.NET Development Server 8.0.0.0
查看源代码:
<html>    <head>    <title>目录清单 -- /web/scripts/</title>      <style>      body {font-family:"Verdana";font-weight:normal;font-size: 8pt;color:black;}         p {font-family:"Verdana";font-weight:normal;color:black;margin-top: -5px}      b {font-family:"Verdana";font-weight:bold;color:black;margin-top: -5px}      h1 { font-family:"Verdana";font-weight:normal;font-size:18pt;color:red }      h2 { font-family:"Verdana";font-weight:normal;font-size:14pt;color:maroon }      pre {font-family:"Lucida Console";font-size: 8pt}      .marker {font-weight: bold; color: black;text-decoration: none;}      .version {color: gray;}      .error {margin-bottom: 10px;}      .expandable { text-decoration:underline; font-weight:bold; color:navy; cursor:hand; }      </style>    </head>    <body bgcolor="white">    <h2> <i>目录清单 -- /web/scripts/</i> </h2></span>            <hr width=100% size=1 color=silver><PRE><A href="/web/"></A> Wednesday, December 16, 2009 12:48 PM      8,670 <A href="swfobject.js">swfobject.js</A>    Monday, December 07, 2009 05:09 PM      1,450 <A href="common.js">common.js</A>Thursday, December 31, 2009 01:54 PM      3,309 <A href="AjaxRequest.js">AjaxRequest.js</A></PRE>            <hr width=100% size=1 color=silver>            <b>版本信息:</b> ASP.NET Development Server 8.0.0.0            </font>    </body></html>
蜘蛛程序分析到"swfobject.js","common.js","AjaxRequest.js"后,如果按上面截取的做法,肯定就错了。这里就不能截取最后的"/",应该是"http://localhost:5995/web/scripts" + "/" + "swfobject.js",但是浏览器为什么能准确分析出来呢?当在页面http://localhost:5995/web/scripts上将鼠标放在超链接swfobject.js上,状态栏显示了它的绝对路径为http://localhost:5995/web/scripts/swfobject.js而不是http://localhost:5995/web/swfobject.js。于是我猜想,肯定在HTTP响应头信息里有相应的信息,于是用下面的代码测试:
try {URL base = new URL("http://localhost:5995/web/scripts");Map<String, List<String>> props = base.openConnection().getHeaderFields();for (Iterator<String> iterator = props.keySet().iterator(); iterator.hasNext();) {String key = (String) iterator.next();System.out.println(key + "=" + props.get(key));}} catch (IOException e) {e.printStackTrace();}
打印信息如下:
localhost:5995null=Date=Content-type=Content-Length=Connection=Server=
从打印内容里,根本看不出里面有什么东西可以区别目录和html文件的,后来又想,如果用Socket模拟浏览器请求,或许有意想不到的收获呢!先贴代码:
public static void main(String[] args) {try {Socket s = new Socket("127.0.0.1", 5995);OutputStream os = s.getOutputStream();os.write(("GET /web/scripts HTTP/1.1\r\n" +"Host: localhost\r\n" +"Connection: keep-alive\r\n" +"\r\n").getBytes());os.flush();InputStream is = s.getInputStream();int c = -1;while ((c = is.read()) != -1) {System.out.print((char)c);}os.close();is.close();} catch (UnknownHostException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}
打印信息如下:
HTTP/1.1 302 FoundServer: ASP.NET Development Server/8.0.0.0Date: Sat, 09 Jan 2010 01:11:42 GMTContent-Length: 135Location: /web/scripts/Connection: Close<html><head><title>Object moved</title></head><body><h2>Object moved to <a href='/website1/scripts/'>here</a>.</h2></body></html>
我想不用我说大家都知道了吧?关键在于浏览器第一次请求http://localhost:5995/web/scripts时,服务器给浏览器一个302的响应,告诉浏览器这个资源被移动到别的地方了,你访问这个路径吧:Location: /web/scripts/,于是浏览器再请求http://localhost:5995/web/scripts/这次后面就多了个"/",于是浏览器就知道这个页面内的所有相对路径的超链接的绝对路径了。^_^
现在知道了用URLConnection测试时,它做了二次请求,所以看不到302的响应。
页: [1]
查看完整版本: 网络爬虫-如何将相对路径转为绝对路径