Java爬虫Java Jsoup爬取csdn等级、排名、访问量、原力等级、个人成就
写在前面
csdn创作数据最多只能查看近一个月的数据(访问量、排名、粉丝数、原力等级、积分、点赞数、收藏数、积分等信息),如果想查看以前的,只能自己保存记录了。
咱们干技术的,总不可能自己天天手动记录,必须是使用程序自动记录每天的数据变化情况,可以使用Java爬虫Jsoup爬取个人博客数据进行记录。记录数据后,时不时查出来看一看,充值一下写博客的动力。
Jsoup简介
Jsoup 是一款 Java 的 HTML 解析器,可直接解析某个 URL 地址,通过请求 URL 地址获取 HTML 文本内容。提供了一套非常省力的API,可通过DOM,CSS 以及类似于 jQuery 的操作方法(类、元素、属性等选择器)来取出和操作数据。
Jsoup依赖 pom.xml
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.15.3</version>
</dependency>
csdn 博客统计数据
csdn 博客主页主要分为 4 部分统计数据:
- 整体统计:访问量、排名、粉丝;
- 原力等级:当前等级、总分;
- 个人成就:点赞、评论、收藏;
- 文章列表:各文章的点赞、阅读、评论、收藏。
下面针对这四种主要统计进行爬取解析。
Jsoup爬取csdn博客原创、排名、粉丝、铁粉
总体统计数据使用 class 选择器,user-profile-statistics-num,博客首页按 F12,选择 Elements,搜索 user-profile-statistics-num 选择器,相关js就是整体统计数据部分。
解析dom代码,通过获取 user-profile-statistics-num 选择器对应的值,就是原创、排名、粉丝、铁粉相关数据。
private static void parseProfiles(Elements elementsProfile) {
for (Element ele : elementsProfile) {
if (ele.parent() == null) {
continue;
}
List<Node> nodes = ele.parent().childNodes();
for (Node node : nodes) {
Attributes attributes1 = node.attributes();
List<Attribute> list = attributes1.asList();
for (Attribute attr : list) {
if ("user-profile-statistics-num".equals(attr.getValue())) {
TextNode nodeNum = (TextNode) node.childNode(0);
// 123
System.out.println("num: " + nodeNum.text());
} else if ("user-profile-statistics-name".equals(attr.getValue())) {
TextNode nodeName = (TextNode) node.childNode(0);
// 总访问量
System.out.println("name: " + nodeName.text());
}
}
}
}
}
Jsoup爬取csdn博客原力等级
原力等级使用 class 选择器,博客首页按 F12,选择 Elements,搜索 influence-left 选择器,相关js就是原力等级相关统计。
解析dom代码,通过获取 user-profile-statistics-num 选择器对应的值,就是原力等级、总分、当月分等相关数据。
private static void parseInfluences(Elements elementsInfluence) {
for (Element ele : elementsInfluence) {
// influence-left
List<Node> nodes = ele.childNodes();
for (Node node : nodes) {
// dl
List<Node> nodesDls = node.childNodes();
// 0 dl 等级,1 dl 总分, 2 a child dl 当月
for (Node nodeDl : nodesDls) {
// dd k(等级), dt v(1)
if (nodeDl instanceof Element eleDl) {
String tagName = eleDl.tagName();
if ("dl".equals(tagName)) {
List<Node> nodesDdDt = nodeDl.childNodes();
handleInfluenceDdDt(nodesDdDt);
} else if ("a".equals(tagName)) {
List<Node> nodesDdDt = eleDl.childNodes().getFirst().childNodes();
handleInfluenceDdDt(nodesDdDt);
}
}
}
}
}
}
Jsoup爬取csdn博客个人成就点赞、评论、收藏
原力等级使用 class 选择器,博客首页按 F12,选择 Elements,搜索 aside-common-box-achievement 选择器,相关js就是个人成就相关统计。
解析dom代码,通过获取 aside-common-box-achievement 选择器对应的值,就是点赞、评论、收藏、代码复制等相关数据。
private static void parseAchievements(Elements elementsAchievement) {
for (Element ele : elementsAchievement) {
// li
List<Node> nodesLi = ele.childNodes();
for (Node li : nodesLi) {
List<Node> nodesDiv = li.childNodes();
for (Node div : nodesDiv) {
if (div instanceof Element eleDiv) {
if ("div".equals(eleDiv.tagName())) {
List<Node> nodes = eleDiv.childNodes();
for (Node span : nodes) {
if (span instanceof Element eleSpan) {
if ("em".equals(eleSpan.tagName())) {
List<Node> ems = eleSpan.childNodes();
Attributes attributes1 = eleSpan.attributes();
List<Attribute> list = attributes1.asList();
for (Attribute attr : list) {
if ("title".equals(attr.getKey())) {
System.out.println("title: " + attr.getValue());
}
}
for (Node nodeEm : ems) {
if (nodeEm instanceof Element eleSpan1) {
TextNode textNode = (TextNode) eleSpan1.childNodes().getFirst();
System.out.println("num: " + textNode.text());
} else if (nodeEm instanceof TextNode textNode) {
System.out.println("name: " + textNode.text());
}
}
TextNode textNode = (TextNode) eleSpan.childNodes().getFirst();
System.out.println("num: " + textNode.text());
} else {
TextNode textNode = (TextNode) eleSpan.childNodes().getFirst();
System.out.println("num: " + textNode.text());
}
} else if (span instanceof TextNode textNode) {
System.out.println("name: " + textNode.text());
}
}
}
}
}
}
}
}
Jsoup爬取csdn博客文章列表阅读、点赞、评论、收藏
原力等级使用 标签 选择器,博客首页按 F12,选择 Elements,搜索 article 选择器,相关js就是博客文章列表相关统计。
解析dom代码,通过获取 article 选择器对应的值,就是阅读、点赞、评论、收藏等相关数据。
private static void parseArticles(Elements articles) {
for (Element art : articles) {
Elements artItem = art.select(".blog-list-box-top");
List<Node> nodes = artItem.getFirst().childNodes();
if (!nodes.isEmpty()) {
Node node = nodes.getFirst();
if (node instanceof Element h4) {
System.out.println("标题:" + h4.text());
}
}
Elements views = art.select(".view-num");
if (!views.isEmpty()) {
Element view = views.getFirst();
if ("span".equals(view.tagName())) {
Node first = view.childNodes().getFirst();
if (first instanceof TextNode tf) {
System.out.println("阅读:" + tf.text());
}
}
}
Elements likes = art.select(".give-like-num");
if (!likes.isEmpty()) {
Element like = likes.getFirst();
if ("span".equals(like.tagName())) {
Node first = like.childNodes().getFirst();
if (first instanceof TextNode tl) {
System.out.println("点赞:" + tl.text());
}
}
}
Elements comments = art.select(".comment-num");
if (comments.size() > 1) {
Element comment = comments.get(0);
if ("span".equals(comment.tagName())) {
Node first = comment.childNodes().getFirst();
if (first instanceof TextNode tf) {
System.out.println("评论:" + tf.text());
}
}
Element comment1 = comments.get(1);
if ("span".equals(comment1.tagName())) {
Node first1 = comment.childNodes().getFirst();
if (first1 instanceof TextNode tf) {
System.out.println("收藏:" + tf.text());
}
}
}
}
}
程序入口
public static void main(String[] args) throws IOException {
// 替换为需要爬的博客首页
String indexUrl = "https://blog.csdn.net/zs";
// 访问博客首页
Document document = Jsoup.connect(indexUrl).get();
// 总访问量、原创、排名、粉丝、铁粉
Elements elementsProfile = document.select(".user-profile-statistics-num");
parseProfiles(elementsProfile);
// 当前等级、当前总分、当月
Elements elementsInfluence = document.select(".influence-bottom");
parseInfluences(elementsInfluence);
// 点赞、评论、收藏、积分
Elements elementsAchievement = document.select(".aside-common-box-achievement");
parseAchievements(elementsAchievement);
// 博客列表每篇 阅读、点赞、评论、收藏
Elements articles = document.getElementsByTag("article");
parseArticles(articles);
}
总结
通过上面的代码,可以使用Java爬虫jsoup轻松爬到csdn相关统计数据。
爬虫虽好,可不要乱用哦!一天请求一次即可,不要疯狂刷新哈。。。
爬到的数据记录到本地,时不时查询总结一番,你也来试试吧~