基于HttpClient和jsoup的爬虫

一、HttpClient

1、httpclient是什么?

官方一点的介绍是:HttpClient是Apache Jakarta Common下的子项目,用来提供高效的、最新的、功能丰富的支持HTTP协议的客户端编程工具包,并且它支持HTTP协议最新的版本和建议。
通过这段时间的学习和使用,在我个人粗陋的理解来看,httpclient其实就是一个模拟浏览器跟服务器通信的工具,它代替了浏览器向服务器发送请求并接收服务器的回应,主要来讲就是报文了,模拟请求然后接收服务器的响应报文配合jsoup解析响应报文从而抓取到自己想要的东西。
但它又不是真正的浏览器,它没有浏览器的将响应报文实体解析成网页、执行内部js等等功能。说白了它的功能就是请求+接收响应。

2、使用步骤

1.jar包下载

官网地址

2.创建httpclient对象

HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();

3.根据请求方法创建请求方法的示例,以请求的服务器url为参数,如get()方法和post()方法

HttpGet httpGet = new HttpGet("www.baidu.com");
HttpPost httpPost = new HttpPost("www.baidu.com");

4.根据上篇介绍的http请求的组成,还要给请求报文设置请求头、请求需要提交的参数信息等,请求的服务器不同,需要的设置也不同,详细的模拟登录再记录,简单的如

//伪装成浏览器
String userAgent="Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101 Safari/537.36";
httpGet.addHeader("User-Agent","useAgent");

5.在设置完相应的参数后,调用httpclient的execute方法发送请求,该方法返回一个httpresponse

CloseableHttpResponse response = httpClient.execute(httpGet);

6.Response即为服务器返回的响应报文,我们可以调用HttpResponse的getEntity()和getHeader()方法获取响应报文的响应实体和响应头,根据http通信机制,一般来说响应报文的报文实体即为服务器返回的网页代码,里面会有相应的信息,我们需要的也就是里面的信息,所以我们可以将返回的网页源代码以字符串的形式保存起来,在我们需要取数据的时候配合jsoup将其解析成DOM。

HttpEntity entity = response.getEntity();
String html = EntityUtils.toString(entity, "utf-8");

7.最后在完成通信后释放连接

httpGet.releaseConnection();

3、完整代码:

pom.xml

<dependencies>
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>4.5.3</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.28</version>
        </dependency>
</dependencies>

get方式获得页面数据

public static void main(String[] args) throws IOException {
        //1.打开浏览器
        CloseableHttpClient httpClient = HttpClients.createDefault();
        //2.声明get请求
        HttpGet httpGet = new HttpGet("http://www.baidu.com/s?wd=java");
        //3.发送请求
        CloseableHttpResponse response = httpClient.execute(httpGet);
        //4.判断状态码
        if(response.getStatusLine().getStatusCode()==200){
            HttpEntity entity = response.getEntity();
           //使用工具类EntityUtils,从响应中取出实体表示的内容并转换成字符串
            String string = EntityUtils.toString(entity, "utf-8");
            System.out.println(string);
        }
        //5.关闭资源
        response.close();
        httpClient.close();
}

二、jsoup

1、什么是jsoup

jsoup 是一款 Java 的HTML 解析器,可直接解析某个URL地址、HTML文本内容。它提供了一套非常省力的API,可通过DOM,CSS以及类似于JQuery的操作方法来取出和操作数据。该版本包含一个支持 HTML5 的解析器分支,可确保跟现在的浏览器一样解析 HTML 的方法,同时降低了解析的时间和内存的占用。
目前使用接触来看,jsoup实现了java后台对页面的操作,就像js对页面的取值,jsoup可以将之前保存的String类型的页面解析成DOM树,调用jsoup封装的方法可以对DOM树节点操作取值。比如:

Document doc = Jsoup.parse(html);

其封装的常用方法总结模拟登录时再总结,亦可参考中文文档Jsoup中文使用手册

2、jsoup使用

1.获得Document对象

使用jsoup解析的HTML可以是一个HTML的字符串,可以是一个URL,可以是一个文件。

从URL获取HTML来解析

// 解析URL地址,参数是url和超时时间
Document doc = Jsoup.parse(new URL("http://www.baidu.com"), 3000);

或者

//get方式
Document doc = Jsoup.connect("http://www.baidu.com/").get();
//post方式
Document doc = Jsoup.connect("http://example.com")
  .data("query", "Java")
  .userAgent("Mozilla")
  .cookie("auth", "token")
  .timeout(3000)
  .post();

从文件获取HTML来解析

 // 解析文件
Document doc = Jsoup.parse(new File("...test.html"), "utf8");
2.获得指定元素

获得Document对象后,接下来就是解析Document对象,并从中获取我们想要的元素了。Document中提供了丰富的方法来获取指定元素。

使用DOM的方式来取得

  • getElementById(String id):通过id来获取
  • getElementsByTag(String tagName):通过标签名字来获取
  • getElementsByClass(String className):通过类名来获取
  • getElementsByAttribute(String key):通过属性名字来获取
  • getElementsByAttributeValue(String key, String value):通过指定的属性名字,属性值来获取
  • getAllElements():获取所有元素

通过类似于css或jQuery的选择器来查找元素

public Elements select(String cssQuery)

例如:

File input = new File("/tmp/input.html");
Document doc = Jsoup.parse(input, "UTF-8", "http://example.com/");

Elements links = doc.select("a[href]"); //带有href属性的a元素
Elements pngs = doc.select("img[src$=.png]");
  //扩展名为.png的图片

Element masthead = doc.select("div.masthead").first();
  //class等于masthead的div标签

Elements resultLinks = doc.select("h3.r > a"); //在h3元素之后的a元素

选择器的更多语法:

选择器 含义
tagname 通过标签查找元素,比如:a
ns|tag 通过标签在命名空间查找元素,比如:可以用 fb
#id 通过ID查找元素,比如:#logo
.class 通过class名称查找元素,比如:.masthead
[attribute] 利用属性查找元素,比如:[href]
[attr=value] 利用属性值来查找元素,比如:[width=500]
* 这个符号将匹配所有元素

selector选择器组合使用

选择器 含义
el#id 元素+ID,比如: div#logo
el.class 元素+class,比如: div.masthead
el[attr] 元素+class,比如: a[href]
ancestor child 查找某个元素下子元素,比如:可以用.body p 查找在"body"元素下的所有 p元素
parent > child 查找某个父元素下的直接子元素,比如:可以用div.content > p

伪选择器selectors

选择器 含义
:lt(n) 查找哪些元素的同级索引值(它的位置在DOM树中是相对于它的父节点)小于n,比如:td:lt(3) 表示小于三列的元素
:gt(n) 查找哪些元素的同级索引值大于n,比如: div p:gt(2)表示哪些div中有包含2个以上的p元素
:eq(n) 查找哪些元素的同级索引值与n相等,比如:form input:eq(1)表示包含一个input标签的Form元素
3、获得数据

通过上面的选择器,我们可以取得一个Elements对象,它继承了ArrayList对象,里面放的全是Element对象。接下来我们要做的就是从Element对象中,取出我们真正需要的内容。

通常有下面几种方法:

  • Element.text():这个方法用来取得一个元素中的文本。

  • Element.html()或Node.outerHtml():这个方法用来取得一个元素中的html内容

  • Node.attr(String key):获得一个属性的值,例如取得超链接中href的值

三、httpclient和jsoup区别

虽然使用jsoup可以直接请求网络地址获得页面数据,可以替代httpclient实现此功能,但是在实际的开发过程中往往会需要使用多线程、连接池、代理等手段实现高效数据抓取,jsoup对这些功能的支持并不好,所以jsoup仅用来作为解析页面的工具使用。

posted @ 2020-11-30 08:39  东的IT备忘录  阅读(513)  评论(0编辑  收藏  举报