关于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办法将图片信息写入到对应的地址当中,实现图片的下载

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理