如何从网站Java下载嵌入式图像

时间:2016-12-19 22:24:31

标签: java readfile

我正在尝试从xkcd网站下载前20张图片/漫画。 如果我将fileName更改为“xkcd.jpg”并将URL更改为“http://imgs.xkcd.com/comics/monty_python.jpg

,我编写的代码允许我下载网站或图像的文本文件

问题在于我需要在网站上下载嵌入的图像,而不必反复复制每个漫画的图像URL ,这违背了该程序的目的。我猜我在某些时候需要一个for循环,但如果我不知道如何在网站上下载嵌入式图像,我就不能这样做。 我希望我的解释不太复杂

以下是我的代码

String fileName = "xkcd.txt";
URL url = new URL("http://xkcd.com/16/");
InputStream in = new BufferedInputStream(url.openStream());
ByteArrayOutputStream out = new ByteArrayOutputStream();
byte[] buf = new byte[1024];
int n = 0;
while (-1 != (n = in.read(buf))) {
    out.write(buf, 0, n);
}
out.close();
in.close();
byte[] response = out.toByteArray();
FileOutputStream fos = new FileOutputStream(fileName);
fos.write(response);
fos.close();

2 个答案:

答案 0 :(得分:0)

这可以使用浏览器的调试控制台和JSoup来解决。

查找图像URL

我们从调试控制台获得了什么(这里是firefox,但应该与任何浏览器一起使用):

enter image description here

这已经很清楚地显示了漫画本身的路径如下:

html -> div with id "middleContainer" -> div with id "comic" -> image element

只需使用" Inspect Element"或者从上下文菜单中在浏览器中调用的任何内容,并且应突出显示相应的元素(如屏幕截图所示)。

我会留下如何弄清楚如何提取相关元素和属性,因为它已经涵盖了很多其他问题,我不想破坏你的项目通过做所有这些;)。

现在可以通过多种方式创建列表:

简单的方法:

帖子都带有顺序ID。只需从第一个问题的编号开始,然后提取该ID并减少相应的编号。如果您有指向特定漫画的硬编码链接,则此方法有效。

有点难,但更通用

实际上这是两种方式,假设你从xkcd.com开始:
1。)

网站上有一些文字,有助于查找相应漫画的ID: enter image description here 从纯文本HTML中提取ID并不是很难,因为它的前/后都有一些在网站上应该非常独特的文本。

2)。

直接从按钮的元素中提取上一个或下一个漫画的路径,以转到下一个/上一个漫画。如上所示,使用开发控制台从HTML文件中提取相应的信息。这种方法应该比第一种方法更具防弹性,因为它只依赖于HTML文件的结构,与其他方法相反。

请注意,上述任何方法只能通过下载嵌入了特定漫画的HTML文件来实现。图片网址不会有太大帮助(除了强力搜索,你不应该因为多种原因而这样做。)

答案 1 :(得分:0)

你可以使用JSoup ...而且它可能是一个更稳定的选项,但如果你只是想要一起破解某些东西,你可能会选择更脆弱的解析HTML方法

    package com.jbirdvegas.q41231970;

    import java.io.BufferedReader;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.net.URL;
    import java.nio.channels.Channels;
    import java.nio.channels.ReadableByteChannel;
    import java.util.stream.Collectors;
    import java.util.stream.IntStream;
    import java.util.stream.Stream;

    public class Download {
        public static void main(String[] args) {
            Download download = new Download();
            // go through each number 1 - 20
            IntStream.range(1, 20)
                    // parse the image url from the html page
                    .mapToObj(download::findImageLinkFromHtml)
                    // download and save each item in the image url list
                    .forEach(download::downloadImage);
        }

        /**
         * Warning manual HTML parsing below...
         * <p>
         * get XKCD image url for a given pageNumber
         *
         * @param pageNumber index of a give cartoon image
         * @return url of the page's image
         */
        private String findImageLinkFromHtml(int pageNumber) {
            // text we are looking for
            String textToFind = "Image URL (for hotlinking/embedding):";
            String url = String.format("https://xkcd.com/%d/", pageNumber);
            try (InputStream inputStream = new URL(url).openConnection().getInputStream();
                 BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) {
                Stream<String> stream = reader.lines();
                String foundLine = stream.filter(lineOfHtml -> lineOfHtml.contains(textToFind))
                        .collect(Collectors.toList()).get(0);
                String[] split = foundLine.split(":");
                return String.format("%s:%s", split[1], split[2]);
            } catch (IOException e) {
                e.printStackTrace();
            }
            return null;
        }

        /**
         * Download a url to a file
         *
         * @param url downloads an image to a local file
         */
        private void downloadImage(String url) {
            try {
                System.out.println("Downloading image url: " + url);
                URL image = new URL(url);
                ReadableByteChannel rbc = Channels.newChannel(image.openStream());
                String[] urlSplit = url.split("/");
                FileOutputStream fos = new FileOutputStream(urlSplit[urlSplit.length - 1]);
                fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

输出:

Downloading image url:  http://imgs.xkcd.com/comics/barrel_cropped_(1).jpg
Downloading image url:  http://imgs.xkcd.com/comics/tree_cropped_(1).jpg
Downloading image url:  http://imgs.xkcd.com/comics/island_color.jpg
Downloading image url:  http://imgs.xkcd.com/comics/landscape_cropped_(1).jpg
Downloading image url:  http://imgs.xkcd.com/comics/blownapart_color.jpg
Downloading image url:  http://imgs.xkcd.com/comics/irony_color.jpg
Downloading image url:  http://imgs.xkcd.com/comics/girl_sleeping_noline_(1).jpg
Downloading image url:  http://imgs.xkcd.com/comics/red_spiders_small.jpg
Downloading image url:  http://imgs.xkcd.com/comics/firefly.jpg
Downloading image url:  http://imgs.xkcd.com/comics/pi.jpg
Downloading image url:  http://imgs.xkcd.com/comics/barrel_mommies.jpg
Downloading image url:  http://imgs.xkcd.com/comics/poisson.jpg
Downloading image url:  http://imgs.xkcd.com/comics/canyon_small.jpg
Downloading image url:  http://imgs.xkcd.com/comics/copyright.jpg
Downloading image url:  http://imgs.xkcd.com/comics/just_alerting_you.jpg
Downloading image url:  http://imgs.xkcd.com/comics/monty_python.jpg
Downloading image url:  http://imgs.xkcd.com/comics/what_if.jpg
Downloading image url:  http://imgs.xkcd.com/comics/snapple.jpg
Downloading image url:  http://imgs.xkcd.com/comics/george_clinton.jpg

另请注意,解析网站存在很多问题... xkcd特别喜欢帮助解析器开发人员发现错误:D请参阅859以获取示例https://xkcd.com/859/