乐趣区

关于http:HTTP客户端获取网页上的图片

给个需要:通过 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 办法将图片信息写入到对应的地址当中,实现图片的下载

退出移动版