基于Java爬取微博数据(四) 获取 图片 or 视频

简介: 【5月更文挑战第14天】基于Java爬取微博数据(四) 图片 or 视频 下载

前面已经讲述了基于 Java 爬取微博正文列表内容,微博用户主页内容以及导出爬取到的微博数据等操作,那么下面讲述一下如何处理微博正文中的图片/视频等内容。

图片 or 视频

对于微博正文来说,图片和视频不能同时存在,也就是说你的微博只能选择发9张以内的图片或者发1个视频,那么在爬取微博正文数据时,想要获取微博中的图片/视频该怎么操作呢?我们首先来看一下微博正文中图片或者视频的一些特点,选择任意一篇微博正文,利用浏览器工具选取任意一张图片

image.png

这里可以看到图片的链接。这里需要说明的是微博正文中的图片链接是做过防盗处理的,你直接复制图片链接到浏览器是无法打开的,但是你可以通过 Java 代码来转存 图片。

image.png

同样的方法,利用浏览器工具的抓取功能获取微博正文视频内容地址,视频内容是可以直接放在浏览器打开的,但是需要注意的是视频内容的链接地址有个有效期参数 Expires ,如果超过有效期再打开会提示 403 错误码

image.png

这里获取的视频链接地址通常是这样的

//locallimit.us.sinaimg.cn/o0/RSkMM0NElx08f30vCBPO01041200MgYx0E010.mp4?label=mp4_720p&template=1280x720.25.0&media_id=5036768815153197&tp=8x8A3El:YTkl0eM8&us=0&ori=1&bf=4&ot=h&lp=0000tfMx8&ps=mZ6WB&uid=66f6G2&ab=,8013-g0,3601-g27&Expires=1716360984&ssig=8XIVHnvPwu&KID=unistore,video

没有请求头 http 或者 https ,那么你可以直接将该链接放在浏览器,浏览器会自动适应请求头,视频内容是可以直接播放的。另外微博的默认请求头就是安全请求头 https

image.png

到这里关于微博正文中的图片 or 视频的大概情况介绍完了,下面可以转存图片 or 视频

转存 图片 or 视频

如果你需要微博正文中的图片 or 视频的话,那么你可以通过 Java 的方式获取图片 or 视频 内容,并转存到其他地方,这里我转存到本地电脑,整个 main 函数的代码如下 DemoWeiBoDown.java

package com.ruoyi.web.controller.demo.controller;

import java.io.BufferedInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;

/**
 * dongao
 * 2024/5/20
 * 5月
 */
public class DemoWeiBoDown {
    public static void main(String[] args) {
        String imageUrl = "https://wx4.sinaimg.cn/orj360/001Q8zQmly1hpy4e694vyj60j60can2r02.jpg";
        String mp4Url = "https://locallimit.us.sinaimg.cn/o0/fn1ZOcw6lx08f0fwPoH601041200BRMn0E010.mp4?label=mp4_720p&template=1280x720.25.0&media_id=5036142555496496&tp=8x8A3El:7fHprYw&us=0&ori=1&bf=4&ot=h&lp=0000tfMx8&ps=mZ6WB&uid=66f6G2&ab=,8013-g0,3601-g36,3601-g27,3601-g27&Expires=1716201414&ssig=B05wQvtmef&KID=unistore,video";
        String filename = imageUrl.substring(imageUrl.lastIndexOf("/") + 1);
        String filename2 = mp4Url.substring(mp4Url.lastIndexOf("/") + 1, mp4Url.indexOf("?"));
        downloadPicture(imageUrl, "E:\\2024weibo\\"+filename);
        downloadPicture(mp4Url, "E:\\2024weibo\\"+filename2);
    }

    /**
     * 下载图片到指定路径
     *
     * @param imageUrl 图片的URL地址
     * @param savePath 图片保存的本地路径
     */
    public static void downloadPicture(String imageUrl, String savePath){

        BufferedInputStream in = null;
        FileOutputStream out = null;
        HttpURLConnection connection = null;
        try {
            // 创建URL对象并打开连接
            URL url = new URL(imageUrl);
            connection = (HttpURLConnection) url.openConnection();
            // 设置请求方法为GET
            connection.setRequestMethod("GET");
            // 建立连接
            connection.connect();

            // 获取响应码并判断是否下载成功
            int responseCode = connection.getResponseCode();
            if (responseCode == HttpURLConnection.HTTP_OK) {
                // 创建输入流和输出流,用于读取和保存图片
                in = new BufferedInputStream(connection.getInputStream());
                out = new FileOutputStream(savePath);

                // 缓冲区,用于一次读取和写入一定量的数据
                byte[] buffer = new byte[1024];
                int bytesRead;
                // 循环读取直到没有数据
                while ((bytesRead = in.read(buffer)) != -1) {
                    out.write(buffer, 0, bytesRead);
                }
                System.out.println("图片/视频 下载成功,保存路径:" + savePath);
            } else {
                // 响应码不为HTTP_OK,下载失败
                System.out.println("无法下载图片/视频,响应码:" + responseCode);
            }

        }catch (Exception e) {
            // 捕获异常并打印堆栈信息
            e.printStackTrace();
        }finally {
            // 无论成功或失败,最后都关闭流和连接
            // 关闭输入流
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    // 将IO异常转为运行时异常抛出
                    throw new RuntimeException(e);
                }
            }
            // 关闭输出流
            if (out != null) {
                try {
                    out.close();
                } catch (IOException e) {
                    // 将IO异常转为运行时异常抛出
                    throw new RuntimeException(e);
                }
            }
            // 关闭连接
            if (connection != null) {
                connection.disconnect();
            }
        }
    }
}

执行当前 main 方法可以看到如下输出情况

image.png

这里的视频 响应码 403 就是因为视频链接的有效期已经过了,更换视频链接地址尝试后如下

image.png

那么这时去到我们的本地文件夹就可以看到刚才转存成功的图片和视频了

image.png

到这里,关于转存微博正文内容中的图片 or 视频的操作就完成了,整个过程比较简单顺畅,当然如果你需要转存到云存储也是可以的,只是需要改造一下获取到图片流 or 视频流后的操作就可以了。

注意点

这里需要说明的是,本文主要是探索基于 Java 爬取微博正文内容图片 or 视频内容实现,以及转存操作,大家有需要的可以相互学习一下。但是注意不可用于非法用途,或者恶意的爬取图片内容等,远离“破坏计算机信息系统罪”,慎重!慎重!慎重!


相关文章
|
13天前
|
算法 Java 数据处理
从HashSet到TreeSet,Java集合框架中的Set接口及其实现类以其“不重复性”要求,彻底改变了处理唯一性数据的方式。
从HashSet到TreeSet,Java集合框架中的Set接口及其实现类以其“不重复性”要求,彻底改变了处理唯一性数据的方式。HashSet基于哈希表实现,提供高效的元素操作;TreeSet则通过红黑树实现元素的自然排序,适合需要有序访问的场景。本文通过示例代码详细介绍了两者的特性和应用场景。
31 6
|
12天前
|
存储 Java API
深入剖析Java Map:不只是存储数据,更是设计艺术的体现!
【10月更文挑战第17天】在Java编程中,Map是一种重要的数据结构,用于存储键值对,并展现了设计艺术的精髓。本文深入剖析了Map的设计原理和使用技巧,包括基本概念、设计艺术(如哈希表与红黑树的空间时间权衡)、以及使用技巧(如选择合适的实现类、避免空指针异常等),帮助读者更好地理解和应用Map。
46 3
|
3天前
|
SQL Java OLAP
java实现“数据平滑升级”
java实现“数据平滑升级”
19 2
|
8天前
|
SQL Java 关系型数据库
java连接mysql查询数据(基础版,无框架)
【10月更文挑战第12天】该示例展示了如何使用Java通过JDBC连接MySQL数据库并查询数据。首先在项目中引入`mysql-connector-java`依赖,然后通过`JdbcUtil`类中的`main`方法实现数据库连接、执行SQL查询及结果处理,最后关闭相关资源。
|
13天前
|
Java
Java Set以其“不重复”的特性,为我们提供了一个高效、简洁的处理唯一性约束数据的方式。
【10月更文挑战第16天】在Java编程中,Set接口确保集合中没有重复元素,每个元素都是独一无二的。HashSet基于哈希表实现,提供高效的添加、删除和查找操作;TreeSet则基于红黑树实现,不仅去重还能自动排序。通过这两个实现类,我们可以轻松处理需要唯一性约束的数据,提升代码质量和效率。
27 2
|
4天前
|
SQL Java OLAP
java实现“数据平滑升级”
java实现“数据平滑升级”
6 0
|
13天前
|
缓存 Java 数据处理
java查询大量数据优化
通过结合的高性能云服务,如其提供的弹性计算资源与全球加速网络,可以进一步增强这些优化策略的效果,确保数据处理环节更加迅速、可靠。蓝易云不仅提供稳定的基础架构,还拥有强大的安全防护和灵活的服务选项,是优化大型数据处理项目不可或缺的合作伙伴。
24 0
|
6天前
|
监控 安全 Java
在 Java 中使用线程池监控以及动态调整线程池时需要注意什么?
【10月更文挑战第22天】在进行线程池的监控和动态调整时,要综合考虑多方面的因素,谨慎操作,以确保线程池能够高效、稳定地运行,满足业务的需求。
76 38
|
4天前
|
安全 Java
java 中 i++ 到底是否线程安全?
本文通过实例探讨了 `i++` 在多线程环境下的线程安全性问题。首先,使用 100 个线程分别执行 10000 次 `i++` 操作,发现最终结果小于预期的 1000000,证明 `i++` 是线程不安全的。接着,介绍了两种解决方法:使用 `synchronized` 关键字加锁和使用 `AtomicInteger` 类。其中,`AtomicInteger` 通过 `CAS` 操作实现了高效的线程安全。最后,通过分析字节码和源码,解释了 `i++` 为何线程不安全以及 `AtomicInteger` 如何保证线程安全。
java 中 i++ 到底是否线程安全?
|
8天前
|
Java 调度
[Java]线程生命周期与线程通信
本文详细探讨了线程生命周期与线程通信。文章首先分析了线程的五个基本状态及其转换过程,结合JDK1.8版本的特点进行了深入讲解。接着,通过多个实例介绍了线程通信的几种实现方式,包括使用`volatile`关键字、`Object`类的`wait()`和`notify()`方法、`CountDownLatch`、`ReentrantLock`结合`Condition`以及`LockSupport`等工具。全文旨在帮助读者理解线程管理的核心概念和技术细节。
23 1
[Java]线程生命周期与线程通信