基于Java爬取微博数据一 微博主页正文列表数据
  • 爬虫背景
  • 爬虫分析
  • 爬取数据
  • 注意点


爬虫背景

最近有这方面的需求,于是就研究了一下通过Java爬取微博数据,由于本人是后端Java开发,因此没有研究其他爬取微博数据的方法,比如通过Python爬取微博数据。大家感兴趣的可以自行查找基于Python爬取微博数据的方法。在爬取微博数据之前,先声明一下,本人爬取的微博数据仅用于测试Java爬取微博数据的可行性,并不会用于其他非正当地方,另外,爬取的数据也都是每个人都可以通过微博客户端正常看到的,不存在爬取隐秘数据的情况。大家在进行爬取数据的操作时也应注意不该爬取非授权数据,防止给自喜提“非法获取计算机信息系统数据罪”“破坏计算机信息系统罪”等。一切爬虫操作都应在合法合规的情况下进行。

爬虫分析

在进行爬虫操作之前,我们先来看一下微博客户端的页面结构,以及对应的请求链接,数据响应情况等,方便为后续爬取微博数据做准备。比如这里打开一个环球网的微博主页:https://weibo.com/u/1686546714 可以看到

基于Java爬取微博数据(一) 微博主页正文列表数据_开发语言


那么我们打开浏览器开发者工具,按F12键,打开开发者工具,选择【网络】或者【network】,然后再次刷新当前页面可以看到如下请求

基于Java爬取微博数据(一) 微博主页正文列表数据_python_02


点击对应的URL,查看URL的响应,最终会找到请求链接 /ajax/statuses/mymblog?uid=1686546714&page=1&feature=0 的响应正是我们需要爬取的数据内容来源


到这里,确定了数据来源URL之后,我们就可以进行后续的爬取数据操作了。

爬取数据

整个爬取数据操作我们需要用到两个 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>
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.

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();
            }
        }
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
  • 77.
  • 78.
  • 79.
  • 80.
  • 81.
  • 82.
  • 83.

代码中请求 URL 中的参数 page 代表当前爬取的是第几页数据,因此代码中进行了字符占位,方便后续的分页数据的替换

基于Java爬取微博数据(一) 微博主页正文列表数据_python_03


爬取微博数据时,必须要为请求 URL 添加 Header 信息 ,增加请求头 Cookie ,没有请求头 Cookie 的话,无法返回正常的响应数据,而是重定向到登录链接地址

基于Java爬取微博数据(一) 微博主页正文列表数据_python_04


那么关于请求头 Cookie 的来源,我们可以到浏览器的【网络】中刚才找到的请求 URL ,点击【标头】 下滑看到如下内容,红框部分就是 Cookie 内容

基于Java爬取微博数据(一) 微博主页正文列表数据_java_05


由于没有登录账号,因此这里的 Cookie 就属于访客 Cookie,那么微博对于访客 Cookie 的数据访问权限比较有限,在通过访客 Cookie 获取数据时,你只能获取当前请求 URL 的前两页数据,每页 20 条,整体也就是 40条数据,如果有置顶微博的话,置顶微博不算在这两页内,那么你就可能会获取到 大于 40 条的微博数据。当你获取 第 3 页数据时,请求链接只返回成功状态,但是没有 data 数据返回

基于Java爬取微博数据(一) 微博主页正文列表数据_java_06


而正常情况下 response.body() 应该返回这样的内容

基于Java爬取微博数据(一) 微博主页正文列表数据_python_07


将 response.body() 数据格式化之后 如图

基于Java爬取微博数据(一) 微博主页正文列表数据_java_08


获取到微博数据之后,在代码中打印的数据内容具体属性 text : 文本内容 reposts_count : 转发数 comments_count : 评论数 attitudes_count : 点赞数

最终的打印结果可以看到如下请求链接返回内容,


到这里我们爬取微博数据就完成了,整个代码逻辑比较清晰,后续对于爬取到的微博数据的处理可以根据具体的业务需求。

另外,对于代码中的正则表达式 String regex = “<[^<>]*>”; 表示的意义:【用于匹配以"<“开头,紧接着是0个或多个不包括”<“和”>“的字符,最后以”>"结尾的字符串。这个正则表达式常用于从一段文本中提取标签内容,例如从

<html><body><h1>Hello, World!</h1></body></html>
  • 1.

中提取出

Hello, World!
  • 1.

在线正则表达式匹配结果如图

基于Java爬取微博数据(一) 微博主页正文列表数据_java_09


当然,微博数据并不是只有这些的,你可以直接将我们爬取数据的请求 URL 放在浏览器看到

基于Java爬取微博数据(一) 微博主页正文列表数据_微博_10

注意点

对于请求 URL 请求头 Cookie 的获取,你可以选择游客 Cookie 或者登录账号后的 Cookie ,这里个人建议使用登录账号后从浏览器拿出的 Cookie,可以获取当前登录账号关注过的用户发布的所有微博数据。关于有效期,百度搜索关于微博登录账号后的 Cookie 有效期是 30天,个人实测了一次,大概十几天后失效,由于中途可能会有其他影响,不一定准确。有时间的大家也可以测一下。不建议使用游客 Cookie 的原因除了获取数据只能获取前 2 页数据外的因素,还有就是不知道具体游客 Cookie 的有效期,有不确定因素在里面,无法保证数据来源稳定了。

到这里可能有人会觉得从浏览器拿出登录后的 Cookie 操作显得不太高级,且比较笨拙,想要通过代码模拟微博登录从而获取 Cookie,这里个人给出的建议是微博目前的登录逻辑安全性较高,需要短信验证且有动态图验证,即使通过扫码登录或者账号登录,验证同样也是多重验证,且不说模拟登录的难度有多大,如果你能成功绕过登录或者模拟登录成功,那么感觉你离“破坏计算机信息系统罪”也不远了。因此个人建议保守一点,手动登录后从浏览器拿出 Cookie 放入爬虫代码中进行数据获取即可,无需费力不讨好的模拟登录。