基于Java爬取微博数据(五) 补充微博正文列表图片 or 视频 内容

2024-08-22 04:36

本文主要是介绍基于Java爬取微博数据(五) 补充微博正文列表图片 or 视频 内容,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

基于Java爬取微博数据五 补充微博正文列表图片 or 视频 内容

  • 数据分析
  • 补充图片 or 视频
  • 执行结果

在通过对微博正文内容中的图片 or 视频内容进行分析后,图片 or 视频 链接是可以直接通过 Java 代码下载或者转存的,那么这样就可以补充我们在 【基于Java爬取微博数据(一) 微博主页正文列表数据】 时缺失的图片 or 视频信息了,当然,如果你的需求并不需要转存微博正文列表内容中的图片 or 视频的话,那么你就无需进行下面的操作了。在开始进行微博主页正文列表数据 补充 图片 or 视频内容之前,先来分析一下获取到的微博正文列表数据的内容。

数据分析

同样的,我们先找到获取微博正文列表数据的 ajax 请求 /ajax/statuses/mymblog?uid=1686546714&page=1&feature=0 的响应返回数据
在这里插入图片描述
获取到微博正文列表请求响应返回的数据之后,我从中取出一个含图片的完整的微博正文 json 对象 以及 一个含视频的完整的微博正文 json 对象来做一个比较
在这里插入图片描述
通过对比工具 Beyond Compare 进行比较这两种情况下返回数据格式的不同,可以看到 含图片的微博正文 返回数据比 含视频的微博正文多了 pic_infos 对象
在这里插入图片描述
继续向下比较可以看到 含图片的微博正文 比 含视频的微博正文 少了 page_info对象 而 page_info对象 里面的 media_info 对象正是视频所在对象
在这里插入图片描述
到这里,对于微博正文列表内容 含图片微博正文 以及 含视频微博正文 的数据格式基本的分析及对比就结束了,下面开始在 获取微博正文列表内容 DemoWeiBo 的 main 方法中补充这一块内容的获取。

补充图片 or 视频

下面开始补充图片 or 视频 链接的获取操作,考虑到视频链接有 Expires 过期时间字段,那么这里在导出 微博正文列表内容 到 Excel 中时保存 转存后的图片 or 视频路径,首先给导出实体类 ExcelData 增加如下字段
在这里插入图片描述
然后在获取微博正文内容列表 main 方法中增加如下代码,这里需要注意的是 pic_ids 和 pic_infos 是配套出现的, pic_ids 的值 就是 pic_infos 子对象的 key
在这里插入图片描述
关于 pic_infos 的子对象包括多种 宽高 尺寸的图片链接地址,你可以根据自己的需要选择不同宽高的图片进行转存
在这里插入图片描述
最后补充的转存微博正文图片的代码如下
在这里插入图片描述
下面再来看获取视频操作,你可以选择 media_info 对象内的以下几种清晰度的视频,
在这里插入图片描述
或者也可以选择 media_info 对象内的 playback_list ,里面是 四种清晰度的视频选择,你可以选择其中一种或者多种清晰度的视频链接
在这里插入图片描述
最终补充获取微博正文视频内容的代码如下
在这里插入图片描述
到这里,补充微博正文内容列表 获取 图片 or 视频的操作就完成了,改造后的 DemoWeiBo.java 代码完整版如下

package com.ruoyi.web.controller.demo.controller;import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;import java.io.BufferedInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;public class DemoWeiBo
{/*** 主函数入口,用于从微博抓取数据并存储到Excel中。** @param args 命令行参数(未使用)* @throws ParseException 当日期解析发生错误时抛出*/public static void main(String[] args) throws ParseException {// 定义微博数据抓取的URL模板String url = "https://weibo.com/ajax/statuses/mymblog?uid=1686546714&feature=0&page=%s";String unfoldurl = "https://weibo.com/ajax/statuses/longtext?id=%s";String cookie = "你的 Cookie";// 初始化日期格式SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//初始化导出Excel数据列表List<ExcelData> excelDataList = new ArrayList<>();// 循环抓取前2页数据for (int i = 1; i <= 3; i++) {try {// 输出开始抓取的提示信息System.out.println("开始获取第" + i + "页数据");// 格式化URL并发送HTTP请求获取响应String urlstr = String.format(url, i);HttpResponse response = HttpUtil.createGet(urlstr).header("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36").header("Cookie",cookie).execute();// 解析响应体String body = response.body();//System.out.println(body);JSONObject jsonObject = JSON.parseObject(body).getJSONObject("data");JSONArray list = null;if (Objects.nonNull(jsonObject)) {// 处理数据列表list = jsonObject.getJSONArray("list");// 遍历并处理每条微博数据for (Object o : list) {JSONObject data = (JSONObject) o;// 解析并处理微博的其他信息Date created = new Date(data.getString("created_at"));System.out.println("created:"+dateFormat.format(created));String regex = "<[^<>]*>";String text = data.getString("text").replaceAll(regex, "");String repost = data.getString("reposts_count");String comment = data.getString("comments_count");String like = data.getString("attitudes_count");//获取微博正文图片信息StringBuffer pic_url = new StringBuffer();Long pic_num = data.getLong("pic_num");if (pic_num > 0 ) {JSONArray pic_ids = data.getJSONArray("pic_ids");JSONObject pic_infos = data.getJSONObject("pic_infos");// 遍历 pic_ids 获取 pic_infos 子对象 keyfor (Object json : pic_ids) {String key = (String) json;JSONObject pic = pic_infos.getJSONObject(key);JSONObject largest = pic.getJSONObject("largest");// 提取图片URL并处理String imageUrl = largest.getString("url");String filename = imageUrl.substring(imageUrl.lastIndexOf("/") + 1);// 下载图片String savePath = "E:\\2024weibo\\" + filename;downloadPicture(imageUrl, savePath);pic_url = pic_url.append(savePath).append(",");}}//获取微博正文视频信息String video_url = "";JSONObject page_info = data.getJSONObject("page_info");if (Objects.nonNull(page_info)) {JSONObject media_info = page_info.getJSONObject("media_info");String mp4_hd_url = media_info.getString("mp4_hd_url");String filename = mp4_hd_url.substring(mp4_hd_url.lastIndexOf("/") + 1, mp4_hd_url.indexOf("?"));// 下载视频String savePath = "E:\\2024weibo\\" + filename;downloadPicture(mp4_hd_url, savePath);video_url = savePath;}//有一种情况,就是当页面文本内容过多的时候,微博默认不展示全部,而是出现 【...展示】 按钮,此时需要再请求一个 URL 获取展开后的文本内容if (text.lastIndexOf("...展开") != -1) {//说明存在 展开 需要重新获取 text 内容String mblogid = data.getString("mblogid");// 格式化URL并发送HTTP请求获取响应String unfoldurlstr = String.format(unfoldurl, mblogid);HttpResponse response2 = HttpUtil.createGet(unfoldurlstr).header("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36").header("Cookie",cookie).execute();// {"ok": 1,"http_code": 200,"data": {}}String body2 = response2.body();JSONObject jsonObject2 = JSONObject.parseObject(body2).getJSONObject("data");String longTextContent = jsonObject2.getString("longTextContent");System.out.println("longTextContent:"+longTextContent);//补全后的内容赋给 texttext = longTextContent;}// 创建ExcelData对象并填充数据ExcelData excelData = new ExcelData();//发布时间excelData.setDate(created);//点赞数excelData.setLike(Long.parseLong(like));//评论数excelData.setComment(Long.parseLong(comment));//转发数excelData.setRepost(Long.parseLong(repost));//原始内容excelData.setContent(text);//图片地址excelData.setImgUrl(pic_url.toString());//视频地址excelData.setVideoUrl(video_url);excelDataList.add(excelData);}}// 输出完成提示并关闭响应,休眠以避免频繁请求System.out.println("第" + i + "页数据获取完毕");response.close();// 如果列表为空,终止循环if (list == null || list.size() == 0) {break;}Thread.sleep(700);} catch (Exception e) {// 打印异常信息e.printStackTrace();}}// 输出开始写入Excel的提示System.out.println("Excel写入数据开始");// 写入Excel的函数调用EasyExcel.write("E:/微博.xlsx", ExcelData.class).sheet("Sheet1").doWrite(excelDataList);System.out.println("Excel写入数据结束");}/*** 下载图片到指定路径** @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();// 设置请求方法为GETconnection.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 方法后的输出 Excel 结果如图
在这里插入图片描述
图片链接和视频链接都已经转存记录成功。

这篇关于基于Java爬取微博数据(五) 补充微博正文列表图片 or 视频 内容的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1095254

相关文章

Java编译生成多个.class文件的原理和作用

《Java编译生成多个.class文件的原理和作用》作为一名经验丰富的开发者,在Java项目中执行编译后,可能会发现一个.java源文件有时会产生多个.class文件,从技术实现层面详细剖析这一现象... 目录一、内部类机制与.class文件生成成员内部类(常规内部类)局部内部类(方法内部类)匿名内部类二、

SpringBoot实现数据库读写分离的3种方法小结

《SpringBoot实现数据库读写分离的3种方法小结》为了提高系统的读写性能和可用性,读写分离是一种经典的数据库架构模式,在SpringBoot应用中,有多种方式可以实现数据库读写分离,本文将介绍三... 目录一、数据库读写分离概述二、方案一:基于AbstractRoutingDataSource实现动态

Python FastAPI+Celery+RabbitMQ实现分布式图片水印处理系统

《PythonFastAPI+Celery+RabbitMQ实现分布式图片水印处理系统》这篇文章主要为大家详细介绍了PythonFastAPI如何结合Celery以及RabbitMQ实现简单的分布式... 实现思路FastAPI 服务器Celery 任务队列RabbitMQ 作为消息代理定时任务处理完整

Springboot @Autowired和@Resource的区别解析

《Springboot@Autowired和@Resource的区别解析》@Resource是JDK提供的注解,只是Spring在实现上提供了这个注解的功能支持,本文给大家介绍Springboot@... 目录【一】定义【1】@Autowired【2】@Resource【二】区别【1】包含的属性不同【2】@

springboot循环依赖问题案例代码及解决办法

《springboot循环依赖问题案例代码及解决办法》在SpringBoot中,如果两个或多个Bean之间存在循环依赖(即BeanA依赖BeanB,而BeanB又依赖BeanA),会导致Spring的... 目录1. 什么是循环依赖?2. 循环依赖的场景案例3. 解决循环依赖的常见方法方法 1:使用 @La

Java枚举类实现Key-Value映射的多种实现方式

《Java枚举类实现Key-Value映射的多种实现方式》在Java开发中,枚举(Enum)是一种特殊的类,本文将详细介绍Java枚举类实现key-value映射的多种方式,有需要的小伙伴可以根据需要... 目录前言一、基础实现方式1.1 为枚举添加属性和构造方法二、http://www.cppcns.co

Elasticsearch 在 Java 中的使用教程

《Elasticsearch在Java中的使用教程》Elasticsearch是一个分布式搜索和分析引擎,基于ApacheLucene构建,能够实现实时数据的存储、搜索、和分析,它广泛应用于全文... 目录1. Elasticsearch 简介2. 环境准备2.1 安装 Elasticsearch2.2 J

使用C#代码在PDF文档中添加、删除和替换图片

《使用C#代码在PDF文档中添加、删除和替换图片》在当今数字化文档处理场景中,动态操作PDF文档中的图像已成为企业级应用开发的核心需求之一,本文将介绍如何在.NET平台使用C#代码在PDF文档中添加、... 目录引言用C#添加图片到PDF文档用C#删除PDF文档中的图片用C#替换PDF文档中的图片引言在当

详解C#如何提取PDF文档中的图片

《详解C#如何提取PDF文档中的图片》提取图片可以将这些图像资源进行单独保存,方便后续在不同的项目中使用,下面我们就来看看如何使用C#通过代码从PDF文档中提取图片吧... 当 PDF 文件中包含有价值的图片,如艺术画作、设计素材、报告图表等,提取图片可以将这些图像资源进行单独保存,方便后续在不同的项目中使

Java中的String.valueOf()和toString()方法区别小结

《Java中的String.valueOf()和toString()方法区别小结》字符串操作是开发者日常编程任务中不可或缺的一部分,转换为字符串是一种常见需求,其中最常见的就是String.value... 目录String.valueOf()方法方法定义方法实现使用示例使用场景toString()方法方法