下载网页时只能下载第一个网页,后续网页虽然能爬出来,但是无法下载到本地。下载网页的代码如下
public class FileDownLoader {
/**根据 url 和网页类型生成需要保存的网页的文件名
去除掉 url 中非文件名字符
*/
public String getFileNameByUrl(String url,String contentType)
{
url=url.substring(7);//remove http://
if(contentType.indexOf("html")!=-1)//text/html
{
url= url.replaceAll("[\?/:|<>\"]", "_")+".html";
return url;
}
else//如application/pdf
{
return url.replaceAll("[\?/:*|<>\"]", "_")+"."+
contentType.substring(contentType.lastIndexOf("/")+1);
}
}
/**保存网页字节数组到本地文件
* filePath 为要保存的文件的相对地址
*/
private void saveToLocal(byte[] data,String filePath)
{
try {
DataOutputStream out=new DataOutputStream(
new FileOutputStream(new File(filePath)));
for(int i=0;i<data.length;i++)
out.write(data[i]);
out.flush();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
/*下载 url 指向的网页*/
public String downloadFile(String url)
{
String filePath=null;
/* 使用 GetMethod 来访问一个 URL 对应的网页,需要如下一些步骤。
1 生成一个 HttpClinet 对象并设置相应的参数。
2 生成一个 GetMethod 对象并设置响应的参数。
3 用 HttpClinet 生成的对象来执行 GetMethod 生成的 Get 方法。
4 处理响应状态码。
5 若响应正常,处理 HTTP 响应内容。
6 释放连接*/
/* 1.生成 HttpClinet 对象并设置参数*/
HttpClient httpClient=new HttpClient();
//设置 Http 连接超时 5s
httpClient.getHttpConnectionManager().getParams().
setConnectionTimeout(5000);
/*2.生成 GetMethod 对象并设置参数*/
//使用 GetMethod 来访问一个 URL 对应的网页
GetMethod getMethod=new GetMethod(url);
//设置 get 请求超时 5s
getMethod.getParams().setParameter(HttpMethodParams.SO_TIMEOUT,5000);
//设置请求重试处理,用的是默认的重试处理:请求三次
getMethod.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,
new DefaultHttpMethodRetryHandler());
/*3.执行 HTTP GET 请求*/
try{
/*executeMethod返回值是一个整数,表示了执行该方法后服务器返回的状态码,
该状态码能表示出该方法执行是否成功,需要认证或者页面发生了跳转(默认状态下GetMethod的实例是自动处理跳转的)*/
int statusCode = httpClient.executeMethod(getMethod);
//判断访问的状态码
if (statusCode != HttpStatus.SC_OK)
{
System.err.println("Method failed: "+ getMethod.getStatusLine());
filePath=null;
}
/*4.处理 HTTP 响应内容(返回的状态码正确后,即可取得内容)*/
/*取得目标地址的内容有三种方法:
1 getResponseBody,该方法返回的是目标的二进制的byte流;
2 getResponseBodyAsString,返回的是String类型,值得注意的是该方法返回的String的编码是根据系统默认的编码方式,所以返回的String值可能编码类型有误
3 getResponseBodyAsStream,这个方法对于目标地址中有大量数据需要传输是最佳的。
在这里我们使用了最简单的getResponseBody方法。*/
byte[] responseBody = getMethod.getResponseBody();//读取为字节数组
//根据网页 url 生成保存时的文件名
filePath="E:\java\web spider\"+getFileNameByUrl(url,
getMethod.getResponseHeader("Content-Type").getValue());
saveToLocal(responseBody,filePath);
} catch (HttpException e) {
// 发生致命的异常,可能是协议不对或者返回的内容有问题
System.out.println("Please check your provided http address!");
e.printStackTrace();
} catch (IOException e) {
// 发生网络异常
e.printStackTrace();
} finally {
// 释放连接
getMethod.releaseConnection();
}
return filePath;
}
}
调用他的爬行代码如下:
public class Crawler {
/* 使用种子 url 初始化 URL 队列*/
String results="";
private void initCrawlerWithSeeds(String[] seeds)
{
for(int i=0;i<seeds.length;i++)
LinkDB.addUnvisitedUrl(seeds[i]);
}
/* 爬取方法*/
public void crawling(String[] seeds,JTextArea kkk)
{
LinkFilter filter = new LinkFilter(){
//提取以 用户输入的URL开头的链接
public boolean accept(String url) {
if(url.startsWith(url))
return true;
else
return false;
}
};
//初始化 URL 队列
initCrawlerWithSeeds(seeds);
//循环条件:待抓取的链接不空且抓取的网页不多于 1000
while(!LinkDB.unVisitedUrlsEmpty()&&LinkDB.getVisitedUrlNum()<=1000)
{
//队头 URL 出对
String visitUrl=LinkDB.unVisitedUrlDeQueue();
if(visitUrl==null)
continue;
FileDownLoader downLoader=new FileDownLoader();
//下载网页
downLoader.downloadFile(visitUrl);
//该 url 放入到已访问的 URL 中
LinkDB.addVisitedUrl(visitUrl);
//提取出下载网页中的 URL
Set<String> links=HtmlParserTool.extractLinks(visitUrl,filter);
Iterator<String> it = links.iterator(); //迭代器
while(it.hasNext())
{
results=results+'\n'+it.next();
}
kkk.setText(results);
}
}
}
求各位大神帮忙解答,马上就要中期检查了