爬虫背景
最近有这方面的需求,于是就研究了一下通过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 包 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 代表当前爬取的是第几页数据,因此代码中进行了字符占位,方便后续的分页数据的替换
爬取微博数据时,必须要为请求 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 放在浏览器看到
注意点
对于请求 URL 请求头 Cookie 的获取,你可以选择游客 Cookie 或者登录账号后的 Cookie ,这里个人建议使用登录账号后从浏览器拿出的 Cookie,可以获取当前登录账号关注过的用户发布的所有微博数据。关于有效期,百度搜索关于微博登录账号后的 Cookie 有效期是 30天,个人实测了一次,大概十几天后失效,由于中途可能会有其他影响,不一定准确。有时间的大家也可以测一下。不建议使用游客 Cookie 的原因除了获取数据只能获取前 2 页数据外的因素,还有就是不知道具体游客 Cookie 的有效期,有不确定因素在里面,无法保证数据来源稳定了。
到这里可能有人会觉得从浏览器拿出登录后的 Cookie 操作显得不太高级,且比较笨拙,想要通过代码模拟微博登录从而获取 Cookie,这里个人给出的建议是微博目前的登录逻辑安全性较高,需要短信验证且有动态图验证,即使通过扫码登录或者账号登录,验证同样也是多重验证,且不说模拟登录的难度有多大,如果你能成功绕过登录或者模拟登录成功,那么感觉你离“破坏计算机信息系统罪”也不远了。因此个人建议保守一点,手动登录后从浏览器拿出 Cookie 放入爬虫代码中进行数据获取即可,无需费力不讨好的模拟登录。
另外说明,本文是把原有的 基于Java爬取微博数据(一) 微博主页正文列表数据 拿过来,而原有的博文将会更名为 基于Java爬取微博数据(完整版),特此说明。