2

我正在尝试从站点下载所有图像,但我不确定这是否是最好的方法,因为我尝试设置用户代理和引荐来源网址无济于事。403 状态错误仅在尝试从 src 页面下载图像时发生,而将所有图像放在一个位置的页面不会显示任何错误并将 src 发送到图像。我不确定是否有办法在不访问 src 页面的情况下下载图像?或者更好的方法来完全做到这一点。到目前为止,这是我的代码。

private static void getPages() throws IOException {

        Document doc = Jsoup.connect("https://manganelo.com/chapter/read_bleach_manga_online_for_free2/chapter_686")
                .get();
        Elements media = doc.getElementsByTag("img");
        System.out.println(media);
        Iterator<Element> ie = media.iterator();
        int i = 1;

        while (ie.hasNext()) {
                Response resultImageResponse = Jsoup.connect(ie.next().attr("src")).ignoreContentType(true)
                        .userAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:78.0) Gecko/20100101 Firefox/78.0")
                        .referrer("www.google.com").timeout(120000).execute();
                FileOutputStream out = (new FileOutputStream(new java.io.File("image #" + i++ + ".jpg")));
                out.write(resultImageResponse.bodyAsBytes());
                out.close();

            }
        
    }
4

1 回答 1

1

您建议的方法存在一些问题:

  1. 您正在尝试使用 JSoup 下载文件内容数据... JSoup 仅适用于文本数据,但不会返回图像内容/值。要下载图像内容,您需要一个 HTTP 请求

  2. 要下载图像,您还需要复制将通过浏览器发出的请求。您可以打开 Chrome,打开开发者工具并打开网络标签。输入您要从中抓取图像的页面的 URL,您会看到正在发出的一堆请求。视图中某处的每个图像都会有一个单独的请求...如果您单击标记为的那个,1.jpg您将看到下载第一个图像的请求,然后您需要复制所有用于请求该图像。您会注意到,请求和响应标头显示在此视图中。成功复制请求后,您就可以开始测试需要哪些标头/cookie。我发现唯一真正的要求是“referer”标头是必要的。

我已经删除了您可能需要/想要的大部分内容,但类似于下面的内容是您所追求的。我已经以全部质量完整地提取了漫画书图像。我引入了一个小型睡眠计时器,以免服务器过载,因为有时您会受到速率限制。即使没有它,您也应该没问题,但您不想被阻止很长一段时间,因此您可以让请求返回给您的速度越慢越好。您甚至可以并行提出请求。

我几乎可以肯定,你可以在下面的一些代码上减少更多,以获得更清晰的结果......但它有效,我假设这已经足够了。

有趣的问题。


import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Iterator;

public class JSoupExample {

    private static int TIMEOUT = 30000;
    private static final int BUFFER_SIZE = 4096;

    public static void main(String... args) throws InterruptedException, IOException {
        String url = "https://manganelo.com/chapter/read_bleach_manga_online_for_free2/chapter_686";
        Document doc = Jsoup.connect(url).get();
        // Select only urls where the source starts with the relevant url (not all images)
        Elements media = doc.select("img[src^=\"https://s5.mkklcdnv5.com/mangakakalot/r1/read_bleach_manga_online_for_free2/chapter_686_death_and_strawberry/\"]");
        Iterator<Element> ie = media.iterator();
        int i = 1;

        while (ie.hasNext()) {
            String imageUrlString = ie.next().attr("src");
            System.out.println(imageUrlString + " ");

            try {
                HttpURLConnection response = makeImageRequest(url, imageUrlString);

                if (response.getResponseCode() == 200) {
                    writeToFile(i, response);
                }
            } catch (IOException e) {
                // skip file and move to next if unavailable
                e.printStackTrace();
                System.out.println("Unable to download file: " + imageUrlString);
            }
            i++; // increment image ID whatever the result of the request.
            Thread.sleep(200l); // prevent yourself from being blocked due to rate limiting
        }
    }

    private static void writeToFile(int i, HttpURLConnection response) throws IOException {
        // opens input stream from the HTTP connection
        InputStream inputStream = response.getInputStream();

        // opens an output stream to save into file
        FileOutputStream outputStream = new FileOutputStream("image_" + i + ".jpg");

        int bytesRead = -1;
        byte[] buffer = new byte[BUFFER_SIZE];
        while ((bytesRead = inputStream.read(buffer)) != -1) {
            outputStream.write(buffer, 0, bytesRead);
        }
        outputStream.close();
        inputStream.close();

        System.out.println("File downloaded");
    }

    private static HttpURLConnection makeImageRequest(String referer, String imageUrlString) throws IOException {
        URL imageUrl = new URL(imageUrlString);
        HttpURLConnection response = (HttpURLConnection) imageUrl.openConnection();

        response.setRequestMethod("GET");
        response.setRequestProperty("referer",  referer);

        response.setConnectTimeout(TIMEOUT);
        response.setReadTimeout(TIMEOUT);
        response.connect();
        return response;
    }
}

我还想确保根据内容类型设置正确的文件扩展名,因为我相信有些是以.png格式而不是.jpeg. 我也相当确定写入文件可以被清理得更简单/更清晰,而不是读取字节流。

于 2020-07-28T13:27:32.713 回答