2024年全新基于Java爬取微博数据(完整版)
- 爬虫背景
- 爬虫分析
- 爬取微博主页正文列表数据
-
- 引入jar包
- 编写代码
- 关于微博 Cookie
- 处理文本的正则
- 微博正文长文本补全
-
- 什么是正文长文本
- 获取正文长文本
- 编写代码
- 导出微博数据到Excel
-
- 引入jar包
- 编写代码
- 突来的疑问
-
- 微博正文内容分析
- 转存 图片 or 视频
- 补充微博正文列表图片 or 视频 内容
-
- 数据分析
- 编写代码
- 执行结果
- 获取微博主页用户数据
-
- 数据分析
- 微博主页用户数据
- 编写代码
- 写在最后
- 注意点
爬虫背景
最近有这方面的需求,于是就研究了一下通过Java爬取微博数据,由于本人是后端Java开发,因此没有研究其他爬取微博数据的方法,比如通过Python爬取微博数据。大家感兴趣的可以自行查找基于Python爬取微博数据的方法。在爬取微博数据之前,先声明一下,本人爬取的微博数据仅用于测试Java爬取微博数据的可行性,并不会用于其他非正当地方,另外,爬取的数据也都是每个人都可以通过微博客户端正常看到的,不存在爬取隐秘数据的情况。大家在进行爬取数据的操作时也应注意不该爬取非授权数据,防止给自己喜提“非法获取计算机信息系统数据罪”“破坏计算机信息系统罪”等。一切爬虫操作都应在合法合规的情况下进行。
爬虫分析
在进行爬虫操作之前,我们先来看一下微博客户端的页面结构,以及对应的请求链接,数据响应情况等,方便为后续爬取微博数据做准备。比如这里打开一个环球网的微博主页:https://weibo.com/u/1686546714 可以看到
那么我们打开浏览器开发者工具,按F12键,打开开发者工具,选择【网络】或者【network】,然后再次刷新当前页面可以看到如下请求
点击对应的URL,查看URL的响应,最终会找到请求链接 /ajax/statuses/mymblog?uid=1686546714&page=1&feature=0 的响应正是我们需要爬取的数据内容来源
到这里,确定了数据来源URL之后,我们就可以进行后续的爬取数据操作了。
爬取微博主页正文列表数据
引入jar包
整个爬取数据操作我们需要用到两个 jar 包 hutool-all 、 fastjson ,那么我们需要首先在项目 pom.xml 文件中引入这两个 jar 包
<!-- hutool-all -->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version> 5.3.4</version>
</dependency>
<!-- 阿里JSON解析器 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.80</version>
</dependency>
编写代码
jar 包引入之后开始编写代码,编写完成后完整代码如下 DemoWeiBo.java
package com.ruoyi.web.controller.demo.controller;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
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";
// 初始化日期格式
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
// 循环抓取3页数据
for (int i = 1; i <= 1; 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 jsonObject2 = JSONObject.parseObject(body).getJSONObject("data");
JSONArray list = null;
if (Objects.nonNull(jsonObject2)) {
// 处理数据列表
list = jsonObject2.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, "");
System.out.println("text:"+text);
String repost = data.getString("reposts_count");
System.out.println("repost:"+repost);
String comment = data.getString("comments_count");
System.out.println("comment:"+comment);
String like = data.getString("attitudes_count");
System.out.println("like:"+like);
}
}
// 输出完成提示并关闭响应,休眠以避免频繁请求
System.out.println("第" + i + "页数据获取完毕");
response.close();
// 如果列表为空,终止循环
if (list == null || list.size() == 0) {
break;
}
Thread.sleep(700);
} catch (Exception e) {
// 打印异常信息
e.printStackTrace();
}
}
}
}
代码中请求 URL 中的参数 page 代表当前爬取的是第几页数据,因此代码中进行了字符占位,方便后续的分页数据的替换
关于微博 Cookie
爬取微博数据时,必须要为请求 URL 添加 Header 信息 ,增加请求头 Cookie ,没有请求头 Cookie 的话,无法返回正常的响应数据,而是重定向到访客页面
那么关于请求头 Cookie 的来源,我们可以到浏览器的【网络】中刚才找到的请求 URL ,点击【标头】 下滑看到如下内容,红框部分就是 Cookie 内容
由于没有登录账号,因此这里的 Cookie 就属于访客 Cookie,那么微博对于访客 Cookie 的数据访问权限比较有限,在通过访客 Cookie 获取数据时,你只能获取当前请求 URL 的前两页数据,每页 20 条,整体也就是 40条数据,如果有置顶微博的话,置顶微博不算在这两页内,那么你就可能会获取到 大于 40 条的微博数据。当你获取 第 3 页数据时,请求链接只返回成功状态,但是没有 data 数据返回
而正常情况下 response.body() 应该返回这样的内容
将 response.body() 数据格式化之后 如图
获取到微博数据之后,在代码中打印的数据内容具体属性 text : 文本内容 reposts_count : 转发数 comments_count : 评论数 attitudes_count : 点赞数
最终的打印结果可以看到如下请求链接返回内容,
到这里我们爬取微博数据就完成了,整个代码逻辑比较清晰,后续对于爬取到的微博数据的处理可以根据具体的业务需求。
处理文本的正则
另外,对于代码中的正则表达式 String regex = “<[^<>]*>”; 表示的意义:【用于匹配以"<“开头,紧接着是0个或多个不包括”<“和”>“的字符,最后以”>"结尾的字符串。这个正则表达式常用于从一段文本中提取标签内容,例如从
<html><body><h1>Hello, World!</h1></body></html>
中提取出
Hello, World!
在线正则表达式匹配结果如图
当然,微博数据并不是只有这些的,你可以直接将我们爬取数据的请求 URL 放在浏览器看到
那么到这里关于 爬取微博主页正文列表数据 的操作就完成了。
微博正文长文本补全
什么是正文长文本
在爬取微博主页正文列表数据的过程中,大家可能不太会注意到这样的微博数据,比如
这样的文本数据有什么特点呢?直观的可以看到 在微博正文结束 出现了【展开】字样,那么这样的微博内容通过Java爬取数据获取到的 text 字段的取值内容是这样的
text:#伊朗将宣布总统莱希等遇难人员葬礼安排#据伊朗国家电视台报道,伊朗政府内阁举行了特别会议,将会宣布伊朗总统莱希等遇难人员的葬礼安排。#伊朗总统莱希等高级官员遇难#据伊朗官方通讯社报道,莱希5月19日在伊朗东阿塞拜疆省出席一个大坝的落成仪式后,其所乘坐的直升机在返回大不里士的途中失事, ...展开
可以看到 text 字段同样返回的内容是有 【展开】 字样的,那么按常理看,微博正文内容肯定时没有获取完整的。那么这个时候就需要补齐长文本了。
获取正文长文本
在微博页面点击【展开】可以看到,触发了ajax 方法 /ajax/statuses/longtext?id=Of8PMwTSJ 获取微博内容详情并补足内容展示
参数 id=Of8PMwTSJ 来自于 爬取微博数据请求链接 /ajax/statuses/mymblog?uid=1686546714&page=1&feature=0 返回的数据
编写代码
下面对于有 【…展开】 字样的微博内容,往往就是需要补足微博长文本内容的,那么可以在代码中增加如下内容
//有一种情况,就是当页面文本内容过多的时候,微博默认不展示全部,而是出现 【...展示】 按钮,此时需要再请求一个 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);
}
其中,cookie和在爬取微博正文内容时用的是同一个cookie,再次执行 main 方法看到如下内容
到这里关于微博主页正文列表中微博正文内容在爬取数据时缺失的 【…展开】里面的文本内容也就补齐了,那么下面我们就可以导出我们爬取到的微博主页正文列表数据到 Excel 中查看了。
导出微博数据到Excel
引入jar包
补全了微博正文内容后,就可以进行下一步操作了,将爬取的微博数据导出到Excel中去,那么首先需要引入 Excel 相关操作 jar 包 ,pom.xml 文件增加
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>3.0.5</version>
</dependency>
编写代码
然后根据所需字段创建导出微博数据的实体对象类 ExcelData.java
package com.ruoyi.web.controller.demo.controller