`
johnson.lee
  • 浏览: 52408 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

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

阅读更多
最近在写一个蜘蛛程序,碰到了一个问题,就是如何将页面内超链接的相对路径转为绝对路径,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/ 

--------------------------------------------------------------------------------

[To Parent Directory]

 Wednesday, December 16, 2009 12:48 PM        8,670 swfobject.js
    Monday, December 07, 2009 05:09 PM        1,450 common.js
  Thursday, 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/">[To Parent Directory]</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>&nbsp;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:5995
null=[HTTP/1.1 200 OK]
Date=[Sat, 09 Jan 2010 01:00:25 GMT]
Content-type=[text/html; charset=utf-8]
Content-Length=[1494]
Connection=[Close]
Server=[ASP.NET Development Server/8.0.0.0]

从打印内容里,根本看不出里面有什么东西可以区别目录和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 Found
Server: ASP.NET Development Server/8.0.0.0
Date: Sat, 09 Jan 2010 01:11:42 GMT
Content-Length: 135
Location: /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
0
分享到:
评论
2 楼 蜗牛笔 2012-06-05  
johnson.lee 写道
其实JDK内置的URLConnection类的getURL()可以获取请求的URL的真实路径,见代码:
try {
	//请求的是服务器的一个目录
	URL url = new URL("http://localhost:5995/web/scripts");
	URLConnection conn = url.openConnection();
	url = conn.getURL();
	System.out.println(url);
} catch (IOException e) {
	e.printStackTrace();
}


打印结果如下:
http://localhost:5995/web/scripts/


因为JDK内置的HttpURLConnection自动处理了302的响应,所以在原来的URL后面加了一个"/",所以当前页面内的相对路径转为绝对路径于是可以通过URLConnection#getURL()返回的路径 + 相对路径即可得到正确的绝对路径了。

你确定?我为什么试着不是这样呢?
1 楼 johnson.lee 2010-03-03  
其实JDK内置的URLConnection类的getURL()可以获取请求的URL的真实路径,见代码:
try {
	//请求的是服务器的一个目录
	URL url = new URL("http://localhost:5995/web/scripts");
	URLConnection conn = url.openConnection();
	url = conn.getURL();
	System.out.println(url);
} catch (IOException e) {
	e.printStackTrace();
}


打印结果如下:
http://localhost:5995/web/scripts/


因为JDK内置的HttpURLConnection自动处理了302的响应,所以在原来的URL后面加了一个"/",所以当前页面内的相对路径转为绝对路径于是可以通过URLConnection#getURL()返回的路径 + 相对路径即可得到正确的绝对路径了。

相关推荐

    PHP利用正则表达式将相对路径转成绝对路径的方法示例

    在进行网站开发或网络爬虫开发时,常常需要处理链接,将相对路径转换为绝对路径是常见需求。相对路径是相对于当前页面的URL,而绝对路径是完整指向资源的URL。本文将展示如何使用PHP中的正则表达式功能,将相对路径...

    爬虫工具辅助工具+curl命令转python代码+自动将网络请求转成python代码

    input 指定保存curl命令的文件路径。例子:D:\curl.txt optional arguments: -h, --help show this help message and exit -o OUTPUT, --output OUTPUT 文件输出目录,不传则与源文件同目录 -n NAME, --...

    Python爬虫基础教程-Urllib详解.pdf

    3. **urllib.parse**:用于解析和构建URL,可以将URL分解为各个部分,如协议、主机、路径等,或者将这些部分组合成新的URL。 4. **urllib.robotparser**:解析robots.txt文件,帮助开发者遵循网站的爬虫规则。 在...

    Node.js-爬取掘金小册并将html文件转为markdown格式文件

    标题 "Node.js-爬取掘金小册并将html文件转为markdown格式文件" 涉及到的技术领域主要是网络爬虫编程以及文件格式转换。在这个项目中,开发者使用Node.js作为主要开发工具,通过HTTP工具模块来抓取掘金小册(一个...

    Python-将epub文件转换为文本

    在IT行业中,Python是一种强大的编程语言,被广泛用于各种任务,包括数据处理、网络爬虫、自动化脚本以及我们今天要讨论的——文件格式转换。本篇将详细讲解如何使用Python将EPUB文件转换为纯文本,这对于文本挖掘、...

    精易模块[源码] V5.15

    1、修复“输入法类”绝对路径不正确BUG。 2、改善“类_内存”读写内存失败返回不正确值问题。感谢易友【stft】建议。 3,网页访问_对象()增加一个参数,用来保存网页返回状态代码。 4、改善(字节集_取左边|取右边|...

    使用Python多线程爬虫爬取电影天堂资源

    由于电影天堂网站使用GBK编码,所以在解析网页时需要先将内容从GBK转为Unicode,以避免乱码问题。 7. **URL管理**:为了避免重复爬取同一个URL,通常需要维护一个已爬取URL的集合。在本例中,使用`CrawledURLs`列表...

    python requests爬取高德地图数据的实例

    在实际部署爬虫时,建议使用相对路径或者动态获取文件保存路径的方式,以便于代码的移植和在不同环境下运行。 最后,本文的代码示例可能由于OCR扫描技术原因,存在少量文字识别错误,需要根据上下文逻辑对这些错误...

    python — 图片爬取.zip

    # 处理相对路径转为绝对路径,如果必要 if img_url.startswith('//'): img_url = 'http:' + img_url elif img_url.startswith('/'): img_url = url + img_url ``` 现在我们有了图片的URL,可以使用`requests`...

    python爬虫之xpath的基本使用详解

    XPath在Python的网络爬虫开发中广泛应用于数据抽取,尤其是在处理结构化的网页数据时。 首先,为了使用XPath,你需要安装`lxml`库,这是Python的一个高效XML和HTML处理库。你可以通过以下命令进行安装: ```bash ...

    一小时Python入门

    - 它适用于广泛的商业应用,如数据科学、网络爬虫等。 - 目前Python已成为很多大学计算机科学课程中的主流入门编程语言。 - 在美国Top10的计算机科学系所中,有8所采用Python作为入门语言。 2. Python环境配置 ...

    Python爬虫基于lxml解决数据编码乱码问题

    在Python爬虫开发中,经常会遇到数据编码导致的乱码问题。当爬取网页内容时,如果不正确地处理字符编码,输出的结果可能会显示为奇怪的符号,如"å·²éª​è¯​ å®​å​¨ ç​¾ç​"。这通常是因为网页的...

    python入门教程大全.pdf 精心整理

    【Python入门教程】系列涵盖了多个基础到进阶的Python知识点,包括了数据导入、网络爬虫、基础语法、错误处理、面试准备、模板库、服务器配置、数据结构、类型操作、异常处理、字符串处理、爬虫开发、应用场景、编码...

    python爬取网页内容转换为PDF文件

    如果不是,它会将相对路径转换为绝对路径,确保在转换为PDF时图片能够正确显示。 整个流程大致如下: 1. 使用`requests.get()`发送HTTP请求,获取网页内容。 2. 使用`BeautifulSoup`解析HTML,提取所需内容,如...

    jsp文件转换成htm文件.zip

    转换时需要确保所有动态内容已正确处理,例如变量、表达式和标签库,以及静态资源(如CSS、JavaScript文件)的引用路径。 在压缩包中的"jsp文件转换成htm文件",可能是提供了一个具体的转换工具或者一个详细的转换...

    swift-RegexSwift正则库

    ", with: { $0.uppercased() })`,这会将第一个匹配项转为大写。 5. **字符串分割**:`split(_:)`方法用于根据正则表达式分割字符串,如`let parts = regex.split("1,2,3,4,5")`,这将返回一个包含每个子串的数组。...

    python编程.pdf

    Python是一种高级语言,具有强大的正则表达式匹配引擎和 strings 模式匹配能力,使其在科学计算、图形化开发系统、脚本、web服务器、网络爬虫、服务器集群、自动化运维等方面应用广泛。Python的哲学和优点使其在开发...

    520_学习总结_第二周1

    在实际应用中,如社交网络或路由网络,图的概念十分常见。图的遍历策略包括深度优先搜索(DFS)和广度优先搜索(BFS)。 二叉树是图的特殊情况,每个节点最多有两个子节点。二叉树在数据库索引(如B+树)、搜索算法...

    python爬取w3shcool的JQuery课程并且保存到本地

    总的来说,Python爬虫是获取网络上公开信息的强大工具,但使用时必须遵守网站的robots.txt规则,尊重版权,并注意不要对网站造成过大的访问压力。在这个案例中,通过Python爬虫技术和网页解析,我们可以便捷地将W3...

    Python如何实现转换URL详解

    本文将深入探讨如何使用Python解析URL并将其拆分为五个关键部分:schema(协议),netloc(网络位置),path(路径),query_params(查询参数)和fragment(片段标识)。我们将通过两个不同的方法来实现这一目标:...

Global site tag (gtag.js) - Google Analytics