提及搜索,你们必定对百度不陌生。每一个搜索引擎后边都是一个大型爬虫调度系统。java
第一篇咱们先以百度为例json
天天都被它爬,今天咱们来爬一下它。数组
url分析服务器
https://image.baidu.com/search/index?tn=baiduimage&ps=1&ct=201326592&lm=-1&cl=2&nc=1&ie=utf-8&word=%E6%A0%A1%E8%8A%B1
这是上图的百度图片地址,咱们能够在http://www.jsons.cn/urlencode/解码一下,就是下面这个 url 地址。网络
能够看到有不少参数,tn ps ct lm cl nc ie word ,通过测试,咱们发现只有 tn 和 word 是有用参数,简单化后的url以下:app
直接请求,发现了下面这个问题。看来咱们简单的发起网络请求是不行的。ide
网络请求工具
咱们知道爬虫的重要一点就是和网络请求打交道,并且请求中最重要的就是HTTP协议,首先发起网络请求。测试
看一下这个 HTTP 工具类,它是 java 原生 HttpURLConnection :ui
package com.javapub.spiderdemo.utils; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; /** * Java原生 HTTP请求 * <p> * 公众号:JavaPub */ public class HttpClient { public static String doGet(String httpurl) { HttpURLConnection connection = null; InputStream is = null; BufferedReader br = null; String result = null;// 返回结果字符串 try { // 建立远程url链接对象 URL url = new URL(httpurl); // 经过远程url链接对象打开一个链接,强转成httpURLConnection类 connection = (HttpURLConnection) url.openConnection(); // 设置链接方式:get connection.setRequestMethod("GET"); // 设置链接主机服务器的超时时间:15000毫秒 connection.setConnectTimeout(15000); // 设置读取远程返回的数据时间:60000毫秒 connection.setReadTimeout(60000); // 发送请求 connection.connect(); // 经过connection链接,获取输入流 if (connection.getResponseCode() == 200) { is = connection.getInputStream(); // 封装输入流is,并指定字符集 br = new BufferedReader(new InputStreamReader(is, "UTF-8")); // 存放数据 StringBuffer sbf = new StringBuffer(); String temp = null; while ((temp = br.readLine()) != null) { sbf.append(temp); sbf.append("\r\n"); } result = sbf.toString(); } } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { // 关闭资源 if (null != br) { try { br.close(); } catch (IOException e) { e.printStackTrace(); } } if (null != is) { try { is.close(); } catch (IOException e) { e.printStackTrace(); } } connection.disconnect();// 关闭远程链接 } return result; } public static String doPost(String httpUrl, String param) { HttpURLConnection connection = null; InputStream is = null; OutputStream os = null; BufferedReader br = null; String result = null; try { URL url = new URL(httpUrl); // 经过远程url链接对象打开链接 connection = (HttpURLConnection) url.openConnection(); // 设置链接请求方式 connection.setRequestMethod("POST"); // 设置链接主机服务器超时时间:15000毫秒 connection.setConnectTimeout(15000); // 设置读取主机服务器返回数据超时时间:60000毫秒 connection.setReadTimeout(60000); // 默认值为:false,当向远程服务器传送数据/写数据时,须要设置为true connection.setDoOutput(true); // 默认值为:true,当前向远程服务读取数据时,设置为true,该参数无关紧要 connection.setDoInput(true); // 设置传入参数的格式:请求参数应该是 name1=value1&name2=value2 的形式。 connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); // 设置鉴权信息:Authorization: Bearer da3efcbf-0845-4fe3-8aba-ee040be542c0 connection.setRequestProperty("Authorization", "Bearer da3efcbf-0845-4fe3-8aba-ee040be542c0"); // 经过链接对象获取一个输出流 os = connection.getOutputStream(); // 经过输出流对象将参数写出去/传输出去,它是经过字节数组写出的 os.write(param.getBytes()); // 经过链接对象获取一个输入流,向远程读取 if (connection.getResponseCode() == 200) { is = connection.getInputStream(); // 对输入流对象进行包装:charset根据工做项目组的要求来设置 br = new BufferedReader(new InputStreamReader(is, "UTF-8")); StringBuffer sbf = new StringBuffer(); String temp = null; // 循环遍历一行一行读取数据 while ((temp = br.readLine()) != null) { sbf.append(temp); sbf.append("\r\n"); } result = sbf.toString(); } } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { // 关闭资源 if (null != br) { try { br.close(); } catch (IOException e) { e.printStackTrace(); } } if (null != os) { try { os.close(); } catch (IOException e) { e.printStackTrace(); } } if (null != is) { try { is.close(); } catch (IOException e) { e.printStackTrace(); } } // 断开与远程地址url的链接 connection.disconnect(); } return result; } }