我是洋葱啊 2016-05-03 10:36 采纳率: 45.5%
浏览 2058
已采纳

网络爬虫下载网页的问题

下载网页时只能下载第一个网页,后续网页虽然能爬出来,但是无法下载到本地。下载网页的代码如下
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);


    }
}

}
求各位大神帮忙解答,马上就要中期检查了

  • 写回答

1条回答 默认 最新

  • devmiao 2016-05-03 23:12
    关注
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 TI的insta-spin例程
  • ¥15 完成下列问题完成下列问题
  • ¥15 C#算法问题, 不知道怎么处理这个数据的转换
  • ¥15 YoloV5 第三方库的版本对照问题
  • ¥15 请完成下列相关问题!
  • ¥15 drone 推送镜像时候 purge: true 推送完毕后没有删除对应的镜像,手动拷贝到服务器执行结果正确在样才能让指令自动执行成功删除对应镜像,如何解决?
  • ¥15 求daily translation(DT)偏差订正方法的代码
  • ¥15 js调用html页面需要隐藏某个按钮
  • ¥15 ads仿真结果在圆图上是怎么读数的
  • ¥20 Cotex M3的调试和程序执行方式是什么样的?