java网络爬虫基础httpclient及jsoup
2021/6/27 20:24:08
本文主要是介绍java网络爬虫基础httpclient及jsoup,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
一、网络爬虫概述
网络爬虫:是一种按照一定的规则,自动地抓取万维网信息的程序或者脚本。
应用场景:
1、实现搜索引擎
当我们经常查询某类数据,可能会在几个或多个不同的渠道来回检索,此时我们便可以通过抓取定向数据进行处理,存储到个人存储库中,比如用到ES,再从ES中进行全文检索就更方便地获取精准数据了。
2、数据分析
当我们需要在某一方面做决策时,可能会需要到大数据做支撑,毕竟在互联网时代,以技术为基础,以数据为驱动,比如当下火爆的自媒体运营,需要分析文章的数据,自己的文章数据分析可以看到,但我还想看竞争对手的或者整个行业的综合数据怎么办?如果手工一遍篇统计相加时非常慢的,此时便可以通过爬虫爬取指定的内容数据,再进行加工处理就可以了。
3、内容生产
当一个新网站刚刚建立,没有内容怎么办,便可以通过爬虫,进行抓取网络资源进行数据采集、加工处理、存储。
二、httpclient
1、无参get请求
通过爬虫获取百度首页
引入依赖包:
<dependencies> <!--HTTP通信库,类似浏览器使用--> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.5.2</version> </dependency> <!--log4j--> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.7.25</version> </dependency> </dependencies>
日志配置:
log4j.rootLogger=DEBUG,stdout log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m%n
实现代码:
public class Crawlerdemo1 { public static void main(String[] args) { //创建一个httpClient对象(打开浏览器) CloseableHttpClient httpClient = HttpClients.createDefault(); //发起get请求,创建HttpGet对象(输入网址) HttpGet httpGet = new HttpGet("http://www.baidu.com"); CloseableHttpResponse response=null; try { //使用httpclient发起请求,返回响应(打开网址) response = httpClient.execute(httpGet); //解析响应获取数据 //获取响应里的状态行里的状态码,请求成功就获取响应体 if(response.getStatusLine().getStatusCode()==200){ //获取响应体对象 HttpEntity httpEntity = response.getEntity(); //解析响应体,获取静态数据 String content = EntityUtils.toString(httpEntity,"utf8"); System.out.println(content.length()); } } catch (IOException e) { e.printStackTrace(); }finally { try { if(response!=null){ response.close(); } httpClient.close(); } catch (IOException e) { e.printStackTrace(); } } } }
结果:
2287
2、带参get请求
通过爬虫获取百度关键词搜索页
public class Crawlerdemo2Parm { public static void main(String[] args) { //创建一个httpClient对象(打开浏览器) CloseableHttpClient httpClient = HttpClients.createDefault(); //请求地址:http://www.baidu.com/s?wd=seo HttpGet httpGet = null; try { //创建URIBuilder URIBuilder uriBuilder = new URIBuilder("http://www.baidu.com/s"); //设置参数 uriBuilder.setParameter("wd","seo"); //发起get请求,创建HttpGet对象(输入网址) httpGet = new HttpGet(uriBuilder.build()); } catch (URISyntaxException e) { e.printStackTrace(); } CloseableHttpResponse response=null; try { //使用httpclient发起请求,返回响应(打开网址) response = httpClient.execute(httpGet); //解析响应获取数据 //获取响应里的状态行里的状态码,请求成功就获取响应体 if(response.getStatusLine().getStatusCode()==200){ //获取响应体对象 HttpEntity httpEntity = response.getEntity(); //解析响应体,获取静态数据 String content = EntityUtils.toString(httpEntity,"utf8"); System.out.println(content.length()); } } catch (IOException e) { e.printStackTrace(); }finally { try { if(response!=null){ response.close(); } httpClient.close(); } catch (IOException e) { e.printStackTrace(); } } } }
结果:
325779
3、无参post请求
post请求只需将不带参数的get修改为post请求方式即可
HttpPost httpPost = new HttpPost("http://www.baidu.com");
结果:
2287
4、带参post请求
没找post提交后返回页面的网页
public class CrawlerPostParmdemo2 { public static void main(String[] args) { //创建一个httpClient对象(打开浏览器) CloseableHttpClient httpClient = HttpClients.createDefault(); //请求地址:https://www.baidu.com/s?wd=seo //创建HttpPost对象,设置uri访问地址 HttpPost httpPost = new HttpPost("https://www.baidu.com/s"); //通过集合封装参数 List<NameValuePair> parms = new ArrayList<NameValuePair>(); parms.add(new BasicNameValuePair("wd","seo")); //创建表单Entity对象 UrlEncodedFormEntity formEntity = null; try { formEntity = new UrlEncodedFormEntity(parms, "utf8"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } //将表单Entity对象设置进post请求中 httpPost.setEntity(formEntity); CloseableHttpResponse response=null; try { //使用httpclient发起请求,返回响应(打开网址) response = httpClient.execute(httpPost); //解析响应获取数据 //获取响应里的状态行里的状态码,请求成功就获取响应体 if(response.getStatusLine().getStatusCode()==200){ //获取响应体对象 HttpEntity httpEntity = response.getEntity(); //解析响应体,获取静态数据 String content = EntityUtils.toString(httpEntity,"utf8"); System.out.println(content.length()); } } catch (IOException e) { e.printStackTrace(); }finally { try { if(response!=null){ response.close(); } httpClient.close(); } catch (IOException e) { e.printStackTrace(); } } } }
5、连接池
每次请求都要创建HttpClient,为了避免频繁的创建连接和关闭连接,可以使用连接池。
public class HttpClientPool { public static void main(String[] args) { //创建连接池管理器 PoolingHttpClientConnectionManager poolCM = new PoolingHttpClientConnectionManager(); //设置最大连接数 poolCM.setMaxTotal(100); //设置一个主机下最大连接数 poolCM.setDefaultMaxPerRoute(10); //使用连接池创建连接 doGet(poolCM); doGet(poolCM); } private static void doGet(PoolingHttpClientConnectionManager poolCM) { //创建httpClient连接对象 CloseableHttpClient httpClient = HttpClients.custom().setConnectionManager(poolCM).build(); //创建get请求 HttpGet httpGet = new HttpGet("http://www.baidu.com"); CloseableHttpResponse response=null; try { response = httpClient.execute(httpGet); if(response.getStatusLine().getStatusCode()==200){ HttpEntity httpEntity = response.getEntity(); String content = EntityUtils.toString(httpEntity, "utf8"); System.out.println(content.length()); } } catch (IOException e) { e.printStackTrace(); }finally { try { if(response!=null){ response.close(); } //此处不用关闭httpClient,由连接池管理 } catch (IOException e) { e.printStackTrace(); } } } }
6、请求参数
在进行请求时,可能会因为网络等原因无法连接,此时需要设置相关的请求最大时间参数。
public class CrawlerConfigdemo { public static void main(String[] args) { //创建一个httpClient对象(打开浏览器) CloseableHttpClient httpClient = HttpClients.createDefault(); //发起get请求,创建HttpGet对象(输入网址) HttpGet httpGet = new HttpGet("http://www.baidu.com"); //设置请求参数 RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(1000) //设置创建连接的最长时间,单位是毫秒 .setConnectionRequestTimeout(500) //设置连接请求的最长时间 .setSocketTimeout(10 * 1000) //设置数据传输的最长时间 .build(); //给请求设置请求参数 httpGet.setConfig(requestConfig); CloseableHttpResponse response=null; try { //使用httpclient发起请求,返回响应(打开网址) response = httpClient.execute(httpGet); //解析响应获取数据 //获取响应里的状态行里的状态码,请求成功就获取响应体 if(response.getStatusLine().getStatusCode()==200){ //获取响应体对象 HttpEntity httpEntity = response.getEntity(); //解析响应体,获取静态数据 String content = EntityUtils.toString(httpEntity,"utf8"); System.out.println(content.length()); } } catch (IOException e) { e.printStackTrace(); }finally { try { if(response!=null){ response.close(); } httpClient.close(); } catch (IOException e) { e.printStackTrace(); } } } }
三、Jsoup
1、jsoup介绍
当我们通过HttpClient抓取到数据后,需要对数据进行处理,可以使用字符串处理工具解析页面,也可以使用正则表达式解析页面,但这些方法会带来很大的开发成本,可以使用专门解析html的技术Jsoup解析。
Jsoup介绍
jsoup是一款Java的HTML解析器,可直接解析某个URL地址、HTML文本内容。它提供了一套非常省力的API, 可通过DOM, CSS以及类似于jQuery的操作方法来取出和操作数据。。
Jsoup参考文档:https://www.open-open.com/jsoup/
jsoup的主要功能如下:。
1.从一个URL,文件或字符串中解析HTML;。
2.使用DOM或CSS选择器来查找、取出数据;
3.可操作HTML元素、属性、文本;。
引入依赖
<dependency> <groupId>org.jsoup</groupId> <artifactId>jsoup</artifactId> <version>1.11.3</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.4</version> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>3.7</version> </dependency>
2、jsoup3种解析方式
1)、url解析
@Test public void testUrl() throws Exception { //解析url地址,第一个参数是url,第二个参数是超时时间 Document doc = Jsoup.parse(new URL("http://www.baidu.com"), 10000); //使用标签选择器选择title标签中的内容 String title = doc.getElementsByTag("title").first().text(); System.out.println(title); }
运行结果:
百度一下,你就知道
PS:虽然使用Jsoup可以替代HttpClient直接发起请求解析数据,但是往往不会这样用,因为实际的开发过程中,需要使用到多线程,连接池,代理等等方式,而jsoup对这些的支持并不是很好,所以我们一-般把jsoup仅仅作为Html解析工具使用。
2)、字符串解析
@Test public void testString() throws IOException { //使用工具类获取文件字符串 String string = FileUtils.readFileToString(new File("C:\\Users\\ztnetbook\\Desktop\\file.html"), "utf8"); //解析字符串 Document doc = Jsoup.parse(string); //使用标签选择器选择title标签中的内容 String title = doc.getElementsByTag("title").first().text(); System.out.println(title); }
运行结果:
百度一下,你就知道
3)、文件解析
@Test public void testFile() throws IOException { //解析文件 Document doc = Jsoup.parse(new File("C:\\Users\\ztnetbook\\Desktop\\file.html"), "utf8"); //使用标签选择器选择title标签中的内容 String title = doc.getElementsByTag("title").first().text(); System.out.println(title); }
运行结果:
百度一下,你就知道
3、使用dom方式遍历文档
元素获取。
1)、根据id查询元素getElementById
//标签是唯一的 Element id = doc.getElementById("Id");
2)、根据标签获取元素getElementsByTag
Element span = doc.getElementsByTag("span").first();
3)、根据class获取元素getElementsByClass
//class可以全部获取,也可以单独获取一个 Element byClass = doc.getElementsByClass("class_a class_b").first();
4)、根据属性获取元素getElementsByAttribute
Element abc = doc.getElementsByAttribute("abc").first(); Elements abc = doc.getElementsByAttributeValue("abc", "123");
元素中获取数据。
Element element = doc.getElementById("Id");
1).从元素中获取 id
String id = element.id();
2).从元素中获取classNames
String className = element.className(); Set<String> set = element.classNames();
3).从元素中获取属性的值attr
String attr = element.attr("abc");
4).从元素中获取所有属性attributes
Attributes attributes = element.attributes();
5).从元素中获取文本内容text
String text = element.text();
4、Selector选择器
1)、tagname:通过标签查找元素,比如: span
Elements elements = doc.select("span");
2)、#id:通过ID查找元素,比如: #id
Element element = doc.select("#id").first();
3)、.class:通过class名称查找元素,比如: .class_ ao
Elements elements = doc.select(".class_a");
4)、[attribute]:利用属性查找元素,比如: [abc]。
Element element = doc.select("[abc]").first();
5)、[attr=value]:利用属性值来查找元素,比如: [class=s_ name]
Elements elements = doc.select("[class=s_ name]");
5、Selector选择器组合
el#id: 元素+ID,比如:h3#id
el.class: 元素+class,比如:li.class_a
el[attr]: 元素+属性名,比如:span[abc]
任意组合: 比如:span[abc].s_ name
ancestor child: 查找某个元素下子元素,比如: .city_ con li查找"city_ con"下的所有li
parent > child: 查找某个父元素下的直接子元素,比如:.abc>ul>li 查找abc第一级(直接子元素)的ul, 再找所有ul下的第一级li。
parent> *: 查找某个父元素下所有直接子元素。
这篇关于java网络爬虫基础httpclient及jsoup的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-26Mybatis官方生成器资料详解与应用教程
- 2024-11-26Mybatis一级缓存资料详解与实战教程
- 2024-11-26Mybatis一级缓存资料详解:新手快速入门
- 2024-11-26SpringBoot3+JDK17搭建后端资料详尽教程
- 2024-11-26Springboot单体架构搭建资料:新手入门教程
- 2024-11-26Springboot单体架构搭建资料详解与实战教程
- 2024-11-26Springboot框架资料:新手入门教程
- 2024-11-26Springboot企业级开发资料入门教程
- 2024-11-26SpringBoot企业级开发资料详解与实战教程
- 2024-11-26Springboot微服务资料:新手入门全攻略