最近接了一个将一个快下线的网站的所有内容都下载下来并离线能正常使用的需求。
最开始是用 Teleport Ultra 来爬的,但是登陆后的内容总是爬不下来,在看了该网站的登陆机制后,觉得可能的原因是:
登陆成功后网站不是响应一个页面出来,而是响应的302状态码,响应的内容是空的。然后前端会再去访问后端,这样响应出来的网页就是登陆后的网页。Teleport Ultra 可能是不支持这样的机制吧。我自己改了前端的登陆界面,绑定了用户名和密码,并将登陆函数设置成加载就执行,再去让Teleport Ultra请求还是不行。最后我只能自己写程序来爬网站了。还有可能是这个登陆是用表单来提交数据的,不知道和这个有没有关系。
*********************************************
欢迎大家来讨论下载不了的原因
**********************************************
java下载网页到本地的程序如下:
public static void main(String []args){
String url = "http://www.pat.aero/gro/users/login";
HttpPost httpPost = new HttpPost(url);
String json = "data[User][username]=XXX&data[User][password]=XXX";
httpPost.addHeader("Content-type", "application/x-www-form-urlencoded; charset=utf-8");
httpPost.setHeader("Accept", "application/json");
// 构建消息实体
StringEntity entity = new StringEntity(json, Charset.forName("UTF-8"));
entity.setContentEncoding("UTF-8");
// 发送Json格式的数据请求
entity.setContentType("application/json");
httpPost.setEntity(entity);
try {
HttpResponse response=client.execute(httpPost);
String getUrl = "http://www.pat.aero/gro/main/";
// 紧接着发送一个get请求
HttpGet httpGet = new HttpGet(getUrl);
HttpResponse execute = client.execute(httpGet);
String startStr = EntityUtils.toString(execute.getEntity(), "utf-8");
genFile(startStr,"start.html");
splitDownloadFile(startStr);
} catch (Exception e) {
logger.error("主函数捕获异常:{}",e.getMessage());
}
}
注:
1、上面的代码只展示了如何去下载一个网页的功能,要是想爬全站的话,还需要把页面中的链接全部分离出来,再去一个个的请求,我实际上采用的深度优先遍历,并剪枝来下载的。剪枝其实就是设置一个set保存所有已经下载过得页面,再根据分离出来的地址去访问的时候先去访问set,如果没有再去请求。
2、对网页中的链接地址也需要遍历去修改,对于js函数,直接去修改下载到对应的js文件中的内容。就可以实现在本地访问了。
由于不同网站有不同的处理方式,代码我就不贴上来了,其实也就是字符串的操作。比较麻烦,写起来还是挺简单的。
多线程是必须的,不然特别慢