【系列教程一】谁说 java 不能做爬虫?我第一个不服!

发布时间:2023-04-25 11:09:53

先做个研究。现在传统的Java后端很卷,找工作也不容易。你有兴趣用Java做爬虫吗(我是后端爬虫)?接下来,我可以发表关于爬虫的文章,包括ip。、js反向、cookie反向爬行、请求响应参数加解密、浏览器指纹分析和常见的反向爬行方法。评论区告诉我!!!

大多数用户可能会认为数据爬取 python 很厉害,其实 java 也很厉害,比如我们今天要介绍的这个工具库:Jsoup。

官方解释如下:

jsoup 是一种处理方法 HTML 的 Java 库。它提供了一些非常方便的东西 API,提取和操作 HTML 例如,页面数据 DOM,CSS 等元素。

由于 jsoup 的 API 该方法使用上和 jQuery 非常接近,所以如果你知道的话 jQuery,然后就可以轻松上手这个框架了。

那怎么用呢?让我们一起来看看!

maven:

<dependency>    <groupId>org.jsoup</groupId>    <artifactId>jsoup</artifactId>    <version>1.14.2</version></dependency>
一、爬网站图片

在爬网站图片之前,我们需要分析网站的结构。我们可以使用浏览器开发人员工具查看网站的源代码。打开网站后,我们可以点击浏览器菜单栏中的“工具”-“开发人员工具”

通过查看请求,我们可以看到该网站的图片是通过以下界面获取的:http://www.cgtpw.com/ctmn/ajax.图灵?act=ctmn&cat_id=0&page=1.其中,page表示页码。我们可以通过修改page的值来获取不同页面的图片。

在了解了网站的结构后,我们可以开始编写Java程序来爬取网站的图片。

二、异步下载图片

爬图时需要注意两个问题:下载图片的数量和速度。如果一次下载大量图片,会占用太多的内存和网络带宽,导致程序运行缓慢。此外,如果下载速度太慢,也会影响程序的运行效率。因此,我们需要使用异步下载技术来解决这个问题。

Java提供了各种异步下载图片的方法,如使用线程池和Java CompletableFuture等。本文将介绍Java的使用 Completablefuture在8中异步下载图片。

首先,我们需要创建一种下载图片的方法。该方法以图片URL为参数,返回CompletableFuture对象,用于异步下载图片。代码如下:

private static CompletableFuture<Void> downloadImage(String imageUrl) {    return CompletableFuture.runAsync(() -> {        try {            URL url = new URL(imageUrl);            HttpURLConnection conn = (HttpURLConnection) url.openConnection();            conn.setRequestMethod("GET");            conn.setConnectTimeout(5000);            conn.setReadTimeout(5000);            conn.connect();            if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {                String fileName = imageUrl.substring(imageUrl.lastIndexOf("/") + 1);                File file = new File("images/" + fileName);                InputStream inputStream = conn.getInputStream();                FileOutputStream outputStream = new FileOutputStream(file);                byte[] buffer = new byte[1024];                int len = -1;                while ((len = inputStream.read(buffer)) != -1) {                    outputStream.write(buffer, 0, len);                }                inputStream.close();                outputStream.close();                System.out.println("Downloaded: " + fileName);            } else {                System.out.println("Failed to download: " + imageUrl);            }        } catch (Exception e) {            System.out.println("Failed to download: " + imageUrl + ", " + e.getMessage());}});}

该方法通过异步下载图片并保存到images目录中。如果下载成功,打印“Downloaded: 否则,打印“文件名”Failed to download: 图片URL”。

接下来,我们需要编写一种批量下载图片的方法。该方法以图片URL列表为参数,使用CompletableFuture。.allOf()将所有异步下载任务合并为Completablefuture对象,并使用join()等待所有任务完成。代码如下:

private static void downloadImages(List<String> imageUrls) {    List<CompletableFuture<Void>> futures = new ArrayList<>();    for (String imageUrl : imageUrls) {        futures.add(downloadImage(imageUrl));    }    CompletableFuture.allOf(futures.toArray(new CompletableFuture[futures.size()])).join();}

该方法将所有异步下载任务合并为Completablefuture对象,并使用join()等待所有任务完成。

三、翻页爬行

由于网站的图片显示在页面上,我们需要编写一种翻页爬行的方法。该方法以页码为参数,获取页面图片URL列表,并通过异步下载下载图片。代码如下:

private static void crawlPage(int page) {    try {        String url = "http://www.cgtpw.com/ctmn/ajax.图灵?act=ctmn&cat_id=0&page=" + page;        Document doc = Jsoup.connect(url).get();        Elements elements = doc.select("p.list-box img");        List<String> imageUrls = new ArrayList<>();        for (Element element : elements) {            String imageUrl = element.attr("data-src");            imageUrls.add(imageUrl);        }        downloadImages(imageUrls);    } catch (Exception e) {        System.out.println("Failed to crawl page: " + page + ", " + e.getMessage());    }}

该方法通过Jsoup库获取网页内容,并分析图片URL列表。然后调用异步下载方法下载图片。如果下载失败,打印“Failed to crawl page: 页码,错误信息”。

最后,我们可以编写一个main方法来执行翻页爬行任务。该方法可以指定起始页码和结束页码,并循环爬取每页图片。代码如下:

public static void main(String[] args) {    int startPage = 1;    int endPage = 10;    for (int i = startPage; i <= endPage; i++) {        crawlPage(i);    }}

该方法从startpage开始,循环爬取每页图片,直到endpage结束。

四、总结

本文介绍了如何用Java爬取网站图片的过程,并采用异步下载和翻页爬取技术,提高爬取效率。爬网站图片时,需要注意下载图片的数量和速度,可以采用异步下载技术来解决这个问题。另外,由于网站的图片是分页显示的,所以我们需要编写一种翻页爬行的方法。在实际开发过程中,还需要考虑网站反爬机制、网络波等其他因素移动和其他问题。如果网站有反爬机制,我们可以使用一些反爬技术,如使用IP代理、设置User-Agent等;如果网络波动导致下载失败,我们可以增加重试机制,使程序更强大。

完整代码奉上:
import org.jsoup.Jsoup;import org.jsoup.nodes.Document;import org.jsoup.nodes.Element;import org.jsoup.select.Elements;import java.io.File;import java.io.FileOutputStream;import java.io.InputStream;import java.net.HttpURLConnection;import java.net.URL;import java.util.ArrayList;import java.util.List;import java.util.concurrent.CompletableFuture;public class TestCrawler {    public static void main(String[] args) {        int startPage = 1;        int endPage = 10;        for (int i = startPage; i <= endPage; i++) {            crawlPage(i);        }    }    private final static String savePath = "C:\\Users\\Administrator\\Desktop\\image\\";    private static CompletableFuture<Void> downloadImage(ImageVO imageVO) {        return CompletableFuture.runAsync(() -> {            try {                String imageUrl  = imageVO.getImageUrl();                URL url = new URL(imageUrl);                HttpURLConnection conn = (HttpURLConnection) url.openConnection();                conn.setRequestMethod("GET");                conn.setConnectTimeout(5000);                conn.setReadTimeout(5000);                conn.connect();                if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {                    String fileName = imageVO.getName()+imageUrl.substring(imageUrl.lastIndexOf(".") );                    File file = new File(savePath + fileName);                    InputStream inputStream = conn.getInputStream();                    FileOutputStream outputStream = new FileOutputStream(file);                    byte[] buffer = new byte[1024];                    int len = -1;                    while ((len = inputStream.read(buffer)) != -1) {                        outputStream.write(buffer, 0, len);                    }                    inputStream.close();                    outputStream.close();                    System.out.println("Downloaded: " + fileName);                } else {                    System.out.println("Failed to download: " + imageUrl);                }            } catch (Exception e) {                System.out.println("Failed to download: " + imageVO.getImageUrl() + ", " + e.getMessage());            }        });    }    private static void downloadImages(List<ImageVO> imageVOList) {        List<CompletableFuture<Void>> futures = new ArrayList<>();        for (ImageVO imageVO : imageVOList) {            futures.add(downloadImage(imageVO));        }        CompletableFuture.allOf(futures.toArray(new CompletableFuture[futures.size()])).join();    }    private static void crawlPage(int page) {        try {            String url = "http://www.cgtpw.com/ctmn/index_" + page + ".html";            Document doc = Jsoup.connect(url).get();            Elements elements = doc.select("ul.listbox2 > li > a > img");            List<ImageVO> imageUrls = new ArrayList<>();            for (Element element : elements) {                ImageVO imageVO = new ImageVO();                String imageUrl = element.attr("src");                String name = element.attr("alt");                imageVO.setName(name);                imageVO.setImageUrl(imageUrl);                imageUrls.add(imageVO);            }            downloadImages(imageUrls);        } catch (Exception e) {            System.out.println("Failed to crawl page: " + page + ", " + e.getMessage());        }    }    public  static  class ImageVO{        public String getName() {            return name;        }        public void setName(String name) {            this.name = name;        }        public String getImageUrl() {            return imageUrl;        }        public void setImageUrl(String imageUrl) {            this.imageUrl = imageUrl;        }        private String name;        private String imageUrl;    }}

上一篇 protobuf太好用,java之父叫我改用grpc
下一篇 LeetCode面试题:合并两个有序数组

文章素材均来源于网络,如有侵权,请联系管理员删除。

标签: Java教程Java基础Java编程技巧面试题Java面试题