用Java Socket请求网页数据,遇到301永久重定向问题

tangmi159 2009-12-05 12:39:57
package wadihu.crawl;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Queue;

/** 爬行类,专门负责网页的下载, 以非阻塞方式连接 */
public class CrawlOrder1 {
private boolean shutdown = false; // 用于控制Connector线程
private Selector selector; // 注册选择器
private Queue<Target> targetLists = new LinkedList<Target>(); // 任务队列
private Queue<Target> taskLists = new LinkedList<Target>(); // 待抓取任务对列
public CrawlOrder1() throws IOException {
selector = Selector.open(); // 打开选择器
RW rw = new RW();
rw.start();
System.out.println("读写线程已启动...");
receiveTarget(); // 用户提交URL任务输入
}

/**用户输入URL请求 */
public void receiveTarget() throws IOException {
BufferedReader buf = new BufferedReader(new InputStreamReader(System.in));
String msg = null;
while((msg = buf.readLine()) != null) {
if(!msg.equals("bye")) {
Target target = new Target(msg);
addTarget(target);
}
else {
shutdown = true;
selector.wakeup();
System.out.println("系统已经停止");
break;
}
}
}

/** 向任务队列添加任务
* @throws IOException */
public void addTarget(Target target) throws IOException {
synchronized (targetLists) {
targetLists.add(target);
}
selector.wakeup();
}

/** 注册读写事件 */
public void registerRW() {
synchronized(targetLists) {
while(targetLists.size() > 0) {
Target target = targetLists.poll();
try {
target.socketChannel.register(selector, SelectionKey.OP_WRITE|SelectionKey.OP_READ, target);
} catch (ClosedChannelException e) {
e.printStackTrace();
}
}
}
}

/** 读写就绪事件发生,处理读写的事件
* @throws IOException */
public void processSelectdRWKeys() throws IOException {
for (Iterator<?> it = selector.selectedKeys().iterator(); it.hasNext();) {
SelectionKey selectionKey = (SelectionKey) it.next();
it.remove();
SocketChannel socketChannel = (SocketChannel) selectionKey.channel();
if(selectionKey.isWritable()) {
String head = "GET / HTTP/1.1\r\nHOST:" + socketChannel.socket().getInetAddress().getHostName() + "\r\n" + "Accept:*/*\r\n" + "User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1;)\r\n\r\n";
ByteBuffer buffer = ByteBuffer.wrap(head.getBytes());
socketChannel.write(buffer);
socketChannel.register(selector, SelectionKey.OP_READ);
} else if(selectionKey.isReadable()) {
ByteBuffer buffer = ByteBuffer.allocate(1024);
int ret = socketChannel.read(buffer);
if (ret < 0) {
socketChannel.close();
selectionKey.cancel();
}
buffer.flip();
Charset ch = Charset.forName("gb2312");
System.out.println(ch.decode(buffer));
}
}
}

/** 建立读写内部类 */
private class RW extends Thread {
public void run() {
while(!shutdown) {
try {
registerRW();
if(selector.select(500) > 0) {
processSelectdRWKeys();
}
} catch (ClosedChannelException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
try {
selector.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) throws IOException {
new CrawlOrder1();
}
}

/** 一项抓取任务,外部类 */
class Target {
SocketAddress address;
SocketChannel socketChannel;
public Target(String host) throws IOException {
address = new InetSocketAddress(InetAddress.getByName(host), 80);
this.socketChannel = SocketChannel.open(address);
this.socketChannel.configureBlocking(false);
}
}
...全文
837 18 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
18 条回复
切换为时间正序
请发表友善的回复…
发表回复
xiaozhuzai0823 2011-12-14
  • 打赏
  • 举报
回复
lz解决了吗??解决了能不能发给我个源码 457014050@qq.com,我也再弄这个啊,愁死了
tangmi159 2009-12-05
  • 打赏
  • 举报
回复
我还发现了个问题,就是我请求www.baidu.com就可以,mp3.baidu.com也可以,但是处理http://blog.csdn.net/ilibaba/archive/2009/02/06/3866537.aspx
这个就不行了,不知道是不是哪里写错了,望熟悉socket的朋友帮忙分析下,感激不尽
tangmi159 2009-12-05
  • 打赏
  • 举报
回复
在我这里有的时候是得不到Location的,不知道为什么
tangmi159 2009-12-05
  • 打赏
  • 举报
回复
我现在想用socket啊,呵呵,以前用java url类是可以的,这个socket不知道怎么处理这个问题
Aniao 2009-12-05
  • 打赏
  • 举报
回复
我也写了蜘蛛,其中要判断返回的代码,遇到重定向的时候,就把里面的Location的URL再请求一次就可以了。

不过如果用apache的http clinet来下载的话,这些功能它都帮你做了
tangmi159 2009-12-05
  • 打赏
  • 举报
回复
执行结果:输入http://blog.csdn.net/ilibaba/archive/2009/02/06/3866537.aspx

返回的结果信息如下
HTTP/1.1 301 Moved Permanently
Server: nginx/0.5.23
Date: Sat, 05 Dec 2009 04:30:10 GMT
Content-Type: text/html
Content-Length: 185
Connection: keep-alive
Location: http://hbdns4.cncmax.cn:8080?HOST=http&R=/&

<html>
<head><title>301 Moved Permanently</title></head>
<body bgcolor="white">
<center><h1>301 Moved Permanently</h1></center>
<hr><center>nginx/0.5.23</center>
</body>
</html>

请问我该怎么处理呢,一天了还没搞好,很多网页都是这个问题,谢谢大家,没太多分了
tangmi159 2009-12-05
  • 打赏
  • 举报
回复
愁死了,没人在吗
tangmi159 2009-12-05
  • 打赏
  • 举报
回复
还有人回到吗
tangmi159 2009-12-05
  • 打赏
  • 举报
回复
来个人给我指导一下呗
whut0802 2009-12-05
  • 打赏
  • 举报
回复
帮顶,学习
tangmi159 2009-12-05
  • 打赏
  • 举报
回复
其实想高效dns解析也是需要单独来做的,瓶颈也存在dns解析的花费上,导致影响下一步
  • 打赏
  • 举报
回复
c是强者
tangmi159 2009-12-05
  • 打赏
  • 举报
回复
呵呵,我还是自己研究下吧,哎
Aniao 2009-12-05
  • 打赏
  • 举报
回复
你要用SOCKET就要知道整个HTTP协议栈里面LOCATION是怎么写的,既然用JAVA,就不要太多考虑效率,不然就用C好了。

JAVA的优势在于方便的架构。

再说了,写蜘蛛用JAVA的瓶颈不再效率,在带宽,我是写过的,100M的带宽,全用HTTPURLCONNECTION,沾满了,才20%的CPU占用率
tangmi159 2009-12-05
  • 打赏
  • 举报
回复
有没有人回答啊 着急死了
tangmi159 2009-12-05
  • 打赏
  • 举报
回复
url效率不怎么样的啊,还有url中的gethost也不怎么样
tangmi159 2009-12-05
  • 打赏
  • 举报
回复
楼上,我知道明白你的意思,可是我问的是如何用Socket来做,呵呵
苍蝇①号 2009-12-05
  • 打赏
  • 举报
回复
用Hjava.net.HttpURLConnection类来代替Socket类,上面帮你封装好了,可以搞定redirect问题

62,635

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧