给个需要:通过HTTP协定来获取指定网页的图片,并下载到本地,且用照片的名字来命名照片。这里我就拿学校的官网来作为指定网页,来实现下载官网图片的性能。
至于如何用HTTP协定制作一个繁难的客户端,能够参考我之前写的一篇文章:
手写一个繁难的安卓客户端:https://segmentfault.com/a/1190000043478702
如何获取官网上的图片信息。首先咱们要晓得,咱们该如何获取网页上的图片信息。咱们通过申请服务器展现图片的网页的相干门路,服务器就会返回一个HTML页面的响应。而这个HTML页面里就有许许多多的<img>标签,图片的相干信息就寄存在这个标签之中。以我学校的官网举例:
所以咱们要做的事件就是利用正则表达式来提取HTML页面中<img>标签。
1、创立一个繁难的http客户端类,连贯到指定的服务端
public class Client { private int port = 80 ;//这个是http协定的默认端口号 private String host = "指定网页的近程地址"; String url; public Client(){ } public Client(int port,String host){ this.port = port; this.host = host; } public void clientServer() throws IOException{ System.out.println("连贯上服务器"); Socket socket = new Socket(host, port); } public void writeToServerGET(OutputStream clientOut,String url ,String host,int port) throws IOException { clientOut.write(("GET" +" "+url+" "+"HTTP/1.1"+"\r\n").getBytes()); clientOut.write(("Accept:"+" "+"text/html"+"\r\n").getBytes()); clientOut.write(("HOST:"+" "+ host+":"+port+"\r\n").getBytes()); clientOut.write(("Connection: "+"keep-alive"+"\r\n").getBytes()); clientOut.write("\r\n".getBytes()); clientOut.flush(); } public static void main(String[] args) throws IOException { new Client().clientServer(); }}
2、在Client类中创立读取输出流的办法readResponse()办法
public String readResponse(BufferedReader bufferedReader) throws IOException { String RSHttp=""; String str = ""; //将读取到的申请报文按行读取 while ((str=bufferedReader.readLine())!= null){ RSHttp +="\r\n" +str; System.out.println(str); } return RSHttp; }
**3、给出getMatchStringSrc()办法以及getMatchStringAlt()办法。
咱们要做的就是提取<img>标签中的src、alt**
public static List<String> getMatchStringAlt(String string){ List<String> alts = new ArrayList<>(); Pattern compile = null ; compile = Pattern.compile("<img.*?>"); Matcher matcher = compile.matcher(getMatchStringClass(string).toString());//这里调用了getMatchStringClass()办法 while (matcher.find()){ String img = matcher.group(); Matcher m = Pattern.compile("alt\\s*=\\s*\"?\\s*(.*?)(\"|>|\\s+)").matcher(img); if(m.find()){ String group = null; group = m.group(); System.out.println(group); alts.add(group.substring(5,group.length()-1)); } } return alts; } public static List<String> getMatchStringSrc( String string){ List<String> pics = new ArrayList<>(); //实例化 compile Pattern compile = null; compile = Pattern.compile("<img.*?>");//利用正则表达式来获取到html中指定的标签<img> //比拟是否寻找到 Matcher matcher = compile.matcher(getMatchStringClass(string).toString()); /* *尝试查找与模式匹配的输出序列的下一个子序列。 当且仅当输出序列的子序列匹配此匹配器的模式时返回:true * */ while (matcher.find()) { String img = matcher.group(); //Matcher得利用Pattern来实例化 Matcher m = Pattern.compile("\"http?(.*?)(\"|>|\\s+)").matcher(img);//利用正则表达式来获取<img>标签中的url m.find(); //group()前一个匹配以字符串模式匹配的子序列(可能为空,就是没有 find()办法没有找到下一个匹配的子序列时为空) String group = m.group(); System.out.println(group); pics.add(group.substring(1, group.length() - 1)); } return pics; }
能够看到,我在getMatchStringSrc()办法以及getMatchStringAlt()办法中还调用了一个getMatchStringClass()办法,这是应为在一个网页中有许许多多的图片信息,以我学校的官网举例:
而咱们要获取的只是那些照片信息,所以不能提取所有的<img>,咱们要把合乎需要的<img>提取进去,所以要利用getMatchStringClass()办法,放大提取的范畴
public static List<String> getMatchStringClass(String string){ List<String> names = new ArrayList<>(); Pattern compile = null; compile =Pattern.compile("<div\\s.*?><img.*?>"); Matcher matcher =compile.matcher(string); while(matcher.find()){ String div = matcher.group(); Matcher m =Pattern.compile("class\\s*=\\s*\"?(.*?)(\"|>|\\s+)").matcher(div); m.find(); String group = null; group = m.group(); if(group.equals("class=\"page_news_lists\"")){//获取class=page_news_lists 的div作为接下来提取<img>标签的范畴 names.add(div); } } return names; }
4、进行逻辑解决
public void clientServer() throws IOException{ System.out.println("连贯上服务器"); Socket socket = new Socket(host, port); //指标门路 url = "/html/cmfy/xiaoyou/"; OutputStream clientOut = socket.getOutputStream(); //发送封装好的申请报文 writeToServerGET(clientOut,url,host,port); System.out.println("url发送胜利"); //获取字节流 InputStream clientIn = socket.getInputStream(); //转为字符流 BufferedReader buf = new BufferedReader(new InputStreamReader(clientIn,"UTF-8")); System.out.println("拆解响应内容"); //读取响应的html String result = readResponse(buf);//调用了readResponse()办法 //将getMatchString()办法返回的图片门路寄存在 picture汇合中 List<String> picture = new ArrayList<>(); picture = getMatchStringSrc(result);//调用了getMatchStringSrc()办法,获取对应图片在网页上的下载门路 int count = picture.size();//汇合的元素个数 System.out.println(count); List<String> alt = new ArrayList<>(); alt = getMatchStringAlt(result);//调用了getMatchStringAlt()办法,获取对应图片的姓名 int count2 = alt.size(); System.out.println(alt); //将SRC转化为字符串按','宰割。 这个办法行不通,将汇合转为字符串之后,有一对'[]'解决不了 /*String SRC = picture.toString(); System.out.println(SRC); */ while(count>0){ //get()返回列表中指定地位的元素。 String name = alt.get(count2-1); String path = picture.get(count-1); System.out.println("还剩"+count+"张"); System.out.println(name); System.out.println(path); //读取到图片门路后下载 URL url = new URL(path); DataInputStream dataInputStream = new DataInputStream(url.openStream()); String newImageName="E://picture/"+name +".jpg";//将图片寄存的门路赋值给newImageName byte[] buffer = new byte[1024]; int length = 0; //关上指定门路的文件夹 newImageName FileOutputStream fileOutputStream = new FileOutputStream(new File(newImageName)); //将图片读入fileOutputStream while((length = dataInputStream.read(buffer))>0){ fileOutputStream.write(buffer,0,length); } System.out.println("上传胜利"); dataInputStream.close(); fileOutputStream.close(); count--; count2--; } clientOut.close(); System.out.println("打印实现"); }
执行!
能够看到,图片曾经下载到本地,且以名字作为图片的命名形式。
总结:
1、我通过浏览器申请学校官网,取得了学校官网的近程地址和端口号
2、创立get_Picture我的项目,首先定义一个port和host,创立构造方法Client(),通过构造方法将port和host传入clentServer()办法中的Socket socket = new Socket(host, port);
3、与服务器进行连贯之后,向服务器发送一个Get申请,申请的门路为"/html/cmfy/xiaoyou/",期待服务器响应
4、将服务器响应的内容通过InputStream读取,再通过BufferedReader将读取到的字节流转化为字符流
5、创立一个读取字符流的办法readResponse()进行按行读取。
6、在clientServer()办法中调用readResponse()办法(将获取到的字符流按行打印),并返回给clientServer()
7、创立一个拆解出html中图片地址的办法getMatchString(),返回一个汇合。
8、clientServer()办法获取到readResponse()办法返回String值之后,调用getMatchStringSrc()办法和getMatchStringAlt()办法,将String值作为参数传入到这两给办法之中
9、getMatchStringSrc()办法和getMatchStringAlt()办法中调用getMatchStringClass()办法,来获取指定地区的图片信息
8、在clientServer()办法中创立一个汇合用来贮存getMatchStringSrc()办法和getMatchStringAlt()办法返回的汇合
9、获取将创立的汇合的长度作为while循环的条件(长度大于0),将汇合中的元素提取进去
10、在clientServer()办法中指定一个门路作为存储图片的中央,应用FileOutputStream类new进去的对象fileOutputStream来关上这个文件,
11、通过fileOutputStream.write办法将图片信息写入到对应的地址当中,实现图片的下载