百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程字典 > 正文

剑走偏锋,我偏要用Java搞爬虫

toyiye 2024-06-21 19:30 33 浏览 0 评论

先做一个调研,现在传统的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.php?act=ctmn&cat_id=0&page=1。其中,page表示页码。我们可以通过修改page的值来获取不同页的图片。

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

二、异步下载图片

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

Java提供了多种异步下载图片的方式,比如使用线程池、使用Java 8中的CompletableFuture等。本文将介绍使用Java 8中的CompletableFuture来异步下载图片。

首先,我们需要创建一个方法来下载图片。该方法接受一个图片的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.php?act=ctmn&cat_id=0&page=" + page;
        Document doc = Jsoup.connect(url).get();
        Elements elements = doc.select("div.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实现爬取http://www.cgtpw.com/ctmn这个网站图片的过程,并采用异步下载和翻页爬取的技术,以提高爬取效率。在爬取网站图片时,我们需要注意下载图片的数量和下载图片的速度,可以采用异步下载的技术来解决这个问题。另外,由于该网站的图片是分页显示的,因此我们需要编写一个方法来翻页爬取。在实际开发过程中,还需要考虑一些其他因素,例如网站反爬机制、网络波动等问题。如果网站有反爬机制,我们可以采用一些反反爬的技术,例如使用代理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;
    }
}

相关推荐

「linux专栏」top命令用法详解,再也不怕看不懂top了

在linux系统中,我们经常使用到的一个命令就是top,它主要是用来显示系统运行中所有的进程和进程对应资源的使用等信息,所有的用户都可以使用top命令。top命令内容量丰富,可令使用者头疼的是无法全部...

Linux 中借助 perf 对 php 程序模拟CPU高的案例分析

导语本文是一篇Linux借助工具分析CPU高的优化案例,没有任何干货内容,很详细的展示了优化CPU高的具体步骤,非常适合初中级读者阅读!...

centos漏洞处理方法(centos podman)

centos服务器最近有诸多漏洞,修复命令及对应的漏洞整理后,分享给大家RHSA-2020:1176-低危:avahi安全更新yumupdateavahi-libsRHSA-2017:326...

Linux上的free命令详解(Buffer和Cache)

解释一下Linux上free命令的输出。下面是free的运行结果,一共有4行。为了方便说明,我加上了列号。这样可以把free的输出看成一个二维数组FO(FreeOutput)。例如:FO[2][1]...

linux 命令行之你真的会用吗?--free 基本用法篇

free命令行统计内存使用率及swap交换分区的使用率数据。是由sourceforge负责维护的,在ubuntu上其包名为procps,这个源码包中,除了free还有ps,top,vmstat,ki...

kong api gateway 初体验(konga github)

kongapigateway初体验(firstsight?)。Kong是一个可扩展的开源API层(也称为API网关或API中间件)。Kong运行在任何RESTfulAPI的前面,并通过插件...

在Ubuntu下开启IP转发的方法(ubuntu20 ip)

IP地址分为公有ip地址和私有ip地址,PublicAddress是由INIC(internetnetworkinformationcenter)负责的,这些IP地址分配给了注册并向INIC提...

基于 Kubernetes 的 Serverless PaaS 稳定性建设万字总结

作者:许成铭(竞霄)数字经济的今天,云计算俨然已经作为基础设施融入到人们的日常生活中,稳定性作为云产品的基本要求,研发人员的技术底线,其不仅仅是文档里承诺的几个九的SLA数字,更是与客户切身利益乃...

跟老韩学Ubuntu Linux系列-sysctl 帮助文档

sysctl一般用于基于内核级别的系统调优,man帮助手册如下。...

如何在 Linux/Unix/Windows 中发现隐藏的进程和端口

unhide是一个小巧的网络取证工具,能够发现那些借助rootkit、LKM及其它技术隐藏的进程和TCP/UDP端口。这个工具在Linux、UNIX类、MS-Windows等操作系统下都...

跟老韩学Ubuntu Server 2204-Linux性能管理-uptime指令帮助手册

uptime指令是每个从事Linux系统工作的相关同学必知必会的指令之一,如下是uptime指令的帮助手册。UPTIME(1)...

Openwrt+Rclone+emby+KODI搭建完美家庭影音服务器

特别声明:本篇内容参考了波仔分享,在此表示感谢!上一篇《Openwrt+emby+KODI搭建家庭影音服务器》只适用影音下载到本地的情形,不能播放云盘中的影音,内容较少,缺少了趣味性,也不直观。...

Linux Shell脚本经典案例(linux shell脚本例子)

编写Shell过程中注意事项:开头加解释器:#!/bin/bash语法缩进,使用四个空格;多加注释说明。命名建议规则:变量名大写、局部变量小写,函数名小写,名字体现出实际作用。默认变量是全局的,在函数...

解决 Linux 性能瓶颈的黄金 60 秒

如果你的Linux服务器突然负载暴增,告警短信快发爆你的手机,如何在最短时间内找出Linux性能问题所在?来看Netflix性能工程团队的这篇博文,看它们通过十条命令在一分钟内对机器性能问题进行诊断。...

跟老韩学Ubuntu Server 2204-Linux性能管理-vmstat指令帮助手册

vmstat可查看ubuntlinux的综合性能,是每个从事Linux人员必知必会、需掌握的核心指令之一。vmstat指令帮助手册如下。VMSTAT(8)...

取消回复欢迎 发表评论:

请填写验证码