爬虫入门系列1-网页下载

爬虫入门系列

本系列文章介绍一下爬虫入门的相关技术,如:

  • 爬虫介绍
  • 网页下载模块
  • 如何分析网页请求
  • 如何按照深度来进行网页抓取
  • 如何在抓取中使用模板
  • 其他一些爬虫相关

爬虫介绍

网络爬虫(又被称为网页蜘蛛,网络机器人,在FOAF社区中间,更经常的称为网页追逐者),是一种按照一定的规则,自动地抓取万维网信息的程序或者脚本。另外一些不常使用的名字还有蚂蚁、自动索引、模拟程序或者蠕虫。—— [ 百度百科 ]

网页下载

网络下载部分是爬虫最重要的组件之一,选择一个好的网络下载工具,能够提高开发效率,节省开发时间。通用的有

项目价格
urlconnectionjdk自带,据我所知,基本爬虫没有使用这个的
httpclientapache提供,大部分爬虫都使用这个
Okhttp谷歌出品,最开始使用在android,现在慢慢在爬虫上也有使用的
htmlunit一个java的无界面浏览器,出发点是好的,兼容性实在是垃圾
selenium+有界面浏览器系列能够访问所有的网页,包括控件,唯一的问题是速度和资源
selenium+phantomjs能够处理很大一部分网页,在linux下也很好,网络渲染也不错,但是在采集某些网页的情况容易出现诡异问题。

本篇文章主要介绍使用httpclient下载网页,以及对httpclient进行初步封装,本篇文章的代码请参考Github

  • 使用httpclient get请求
  • 使用httpclient post请求
  • 封装httpclient

使用httpclient get请求

  • 声明一个httpclient对象
  • 声明httpget方法,通过这个方法get请求具体的url
  • 执行httpget请求
  • 取得网页源码

下面是httpclient官方网站的一个例子


import java.io.IOException;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

public class ClientWithResponseHandler {

    public final static void main(String[] args) throws Exception {
        // 声明一个httpclient对象,然后所有的访问都使用这个httpclient
        CloseableHttpClient httpclient = HttpClients.createDefault();
        try {
            // 声明httpget方法,通过这个方法get请求具体的url
            HttpGet httpget = new HttpGet("http://httpbin.org/");
            // 输出结果 GET http://httpbin.org/ HTTP/1.1
            // GET 请求方法
            // http://httpbin.org/ 请求url
            // HTTP/1.1 请求的http协议
            System.out.println("Executing request " + httpget.getRequestLine());

            // 这个在一般的爬虫中不需要这么处理,可以换一种方式
            // Create a custom response handler
            ResponseHandler<String> responseHandler = new ResponseHandler<String>() {

                @Override
                public String handleResponse(
                        final HttpResponse response) throws ClientProtocolException, IOException {
                    int status = response.getStatusLine().getStatusCode();
                    if (status >= 200 && status < 300) {
                        HttpEntity entity = response.getEntity();
                        return entity != null ? EntityUtils.toString(entity) : null;
                    } else {
                        throw new ClientProtocolException("Unexpected response status: " + status);
                    }
                }

            };
            // 执行httpget请求 这里可以使用下面的代码
            String responseBody = httpclient.execute(httpget, responseHandler);
            System.out.println("----------------------------------------");
            // 输出网页源码
            System.out.println(responseBody);
        } finally {
            httpclient.close();
        }
    }

}

使用httpclient post请求

使用httpclient 进行post请求和get请求很类似
- 声明一个httpclient对象
- 声明httppost方法,通过这个方法post请求具体的url
- 将post数据添加到httppost对象上
- 执行httppost请求
- 取得网页源码

这里本想使用hc官网例子,但是官网例子是提交文件,不适合初学者,所以使用其他例子。

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;

import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

public class Snippet {
    public static void main(String[] args) {
        CloseableHttpClient httpClient = HttpClients.createDefault();
        try {
            // httppost的url 这里用上本机的某个工程做测试
            HttpPost post = new HttpPost("http://localhost/....");
            // 创建参数列表,这里是form表单的形式
            List<NameValuePair> list = new ArrayList<NameValuePair>();
            list.add(new BasicNameValuePair("j_username", "admin"));
            list.add(new BasicNameValuePair("j_password", "admin"));
            // url格式编码
            UrlEncodedFormEntity uefEntity = new UrlEncodedFormEntity(list, "UTF-8");
            // 将postdata添加到post方法上
            post.setEntity(uefEntity);
            // 执行请求
            CloseableHttpResponse httpResponse = httpClient.execute(post);
            try {
                HttpEntity entity = httpResponse.getEntity();
                if (null != entity) {
                    System.out.println("-------------------------------------------------------");
                    System.out.println(EntityUtils.toString(uefEntity));
                    System.out.println("-------------------------------------------------------");
                }
            } finally {
                httpResponse.close();
            }

        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                httpClient.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

封装httpclient

封装httpclient是对爬虫开发工作是十分重要的,封装的好处。

  • 统一调用HttpGet ,HttpPost方法
  • 方便对httpclient进行升级,或者改变为其他的请求组件,如OKHttp等
  • 代码复用,便于阅读
  • 所有功能统一处理

以上面两个例子为例,将相同部分统一处理 (注意,这里只是初步封装,代码未经测试,具体请以Github上为准)

没啥说的这里肯定使用一个了。

        // 声明一个httpclient对象,然后所有的访问都使用这个httpclient
        CloseableHttpClient httpClient = HttpClients.createDefault();

这里是不一样的,每次访问都需要new的,那有相同的吗?答案是有 通过观察类结构发现 httpget和httpPost都继承过HttpRequestBase类,那么好可以改写成

            // 声明httpget方法,通过这个方法get请求具体的url
            HttpGet httpget = new HttpGet("http://httpbin.org/");
            // httppost的url 这里用上本机的某个工程做测试
            HttpPost post = new HttpPost("http://localhost/....");

            // 初步封装后
            String methodstr = "get";
            HttpRequestBase method = null;
            if ("get".equals(methodstr)) {
                method = new HttpGet("");
            } else {
                HttpPost post = new HttpPost("");
                List<NameValuePair> list = new ArrayList<NameValuePair>();
                list.add(new BasicNameValuePair("j_username", "admin"));
                list.add(new BasicNameValuePair("j_password", "admin"));
                // url格式编码
                UrlEncodedFormEntity uefEntity = new UrlEncodedFormEntity(list, "UTF-8");
                // 将postdata添加到post方法上
                post.setEntity(uefEntity);
                method = post;
            }

这里尽管例子代码就这些,但是实际有很多需要处理的比如302处理,404处理,网页编码或字节处理,或传输方式处理,这些都要在下面这段代码处理

            // 执行请求
            CloseableHttpResponse httpResponse = httpClient.execute(post);
            try {
                HttpEntity entity = httpResponse.getEntity();
                if (null != entity) {
                    System.out.println("-------------------------------------------------------");
                    System.out.println(EntityUtils.toString(uefEntity));
                    System.out.println("-------------------------------------------------------");
                }
            } finally {
                httpResponse.close();
            }

完整代码请点击这里
完整代码请点击这里
完整代码请点击这里

总结

httpclient是一个十分好用的工具,这里只是初步介绍一下,作者水平有限,可能有错误的地方欢迎指正,转载请注明出处(http://blog.csdn.net/qq329966505/article/details/52145024),谢谢

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值