文章目录
#一、项目简介
该项目基于 okhttp3、jsoup、gson 第三方库对 GitHub 上的 awesome-java 项目进行爬取并获取各个子项目的相关信息(Star收藏数、Fork分支数、Issues问题数),然后根据 Star 数从高到低的顺序进行排序表示项目的活跃程度,并通过 ECharts 图表框架制作一个简易的 Star 日榜,实现一个类似于 “GitHub趋势” 的功能。
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210317160934853.png)
二、主要模块
1.获取页面: 向服务器发送请求,通过第三方库 okhttp 获取指定 url 对应的 html 页面
public String getPage(String url) throws IOException {
//1.创建一个 OkHttpClient 对象
okHttpClient = new OkHttpClient();
//2.创建一个 Request 对象
Request request = new Request.Builder().url(url).build();
//3.创建一个 Call 对象
Call call = okHttpClient.newCall(request);
//4.创建一个 Response 对象
Response response = call.execute();
//5.判断响应是否成功
if (!response.isSuccessful()) {
System.out.println("请求失败!");
return null;
}
return response.body().string();
}
2.分析页面
1.通过第三方库 jsoup 解析 html 页面结构,生成 document 对象(树形结构的文档),使用 getElementsByTag() 获取< li >,进一步获取< a >,< a >中 href 属性里的 url 就是我们需要统计的项目主页链接,存储到 Project 对象中
public List<Project> parseProjectList(String html) {
ArrayList<Project> result = new ArrayList<>();
//1.使用 parse() 将 html 解析为 document 对象
Document document = Jsoup.parse(html);
//2.使用 getElementsByTag() 获取所有的<li>
Elements elements = document.getElementsByTag("li");
for (Element li : elements) {
//3.获取<li>中的<a>
Elements allLink = li.getElementsByTag("a");
if (allLink.size() == 0) {
continue;
}
Element link = allLink.get(0);
//4.获取 href 属性中的内容
String url = link.attr("href");
if (!url.startsWith("https://github.com")) {
continue;
}
if (urlBlackList.contains(url)) {
continue;
}
//5.存储到 Project 中
Project project = new Project();
project.setName(link.text());
project.setUrl(link.attr("href"));
project.setDescription(li.text());
result.add(project);
}
return result;
}
2.遍历项目列表,通过 GitHub 官方提供的 API 获取项目信息,第三方库 gson 进行解析,获取项目数据
通过 url 获取仓库名,例如 https://github.com/doov-io/doov => doov-io/doov
public String getRepoName(String url) {
int lastOne = url.lastIndexOf("/");
int lastTwo = url.lastIndexOf("/", lastOne - 1);
if (lastOne == -1 || lastTwo == -1) {
System.out.println("当前 url 不合法");
return null;
}
return url.substring(lastTwo + 1);
}
通过 GitHub API 获取仓库的项目信息,例如 https://api.github.com/repos/doov-io/doov
public String getRepoInfo(String repoName) throws IOException {
String username = "huangwu1026";
String password = "DiL971026";
//进行身份验证
String credential = Credentials.basic(username, password);
String url = "https://api.github.com/repos/" + repoName;
Request request = new Request.Builder().url(url).header("Authorization", credential).build();
Call call = okHttpClient.newCall(request);
Response response = call.execute();
if (!response.isSuccessful()) {
System.out.println("请求失败! url = " + url);
return null;
}
return response.body().string();
}
通过第三方库 gson 解析页面,将获取项目数据(star、fork、issues)存储到 Project 对象中
public void parseRepoInfo(String jsonString, Project project) {
//TypeToken 是数据类型转换器
Type type = new TypeToken<HashMap<String, Object>>() {
}.getType();
//将 Json 数据转换为对象
HashMap<String, Object> hashMap = gson.fromJson(jsonString, type);
Double starCount = (Double) hashMap.get("stargazers_count");
project.setStarCount(starCount.intValue());
Double forkCount = (Double) hashMap.get("forks_count");
project.setForkCount(forkCount.intValue());
Double openedIssueCount = (Double) hashMap.get("open_issues_count");
project.setOpenIssueCount(openedIssueCount.intValue());
}
Project 类用于存储
@Getter
@Setter
@ToString
public class Project {
//项目名字,对应<a>中的内容
private String name;
//项目主页链接,对应<a>中的 href 属性
private String url;
//项目描述信息,对应<li>中的内容
private String description;
//需要统计的数据
private int starCount;
private int forkCount;
private int openIssueCount;
}
3.数据存储: 通过 JDBC 操作 MySQL 数据库将 Project 对象存储到 project_table 表中
1.设计表结构
create database java_github_crawler;
create table project_table(
name varchar(50),
url varchar(1024),
description varchar(1024),
startCount int,
forkCount int,
openedIssueCount int,
date carchar(128)
);
2.DBUtil 类管理数据库连接
public class DBUtil {
private static String url = "jdbc:mysql://localhost:3306/java_github_crawler?useSSL=true&characterEncoding=UTF-8";
private static String username = "root";
private static String password = "123456";
private static volatile DataSource dataSource = null;
//单例模式-懒汉式
private static DataSource getDataSource() {
if (dataSource == null) {
synchronized (DataSource.class) {
if (dataSource == null) {
dataSource = new MysqlDataSource();
MysqlDataSource mysqlDataSource = (MysqlDataSource) dataSource;
mysqlDataSource.setURL(url);
mysqlDataSource.setUser(username);
mysqlDataSource.setPassword(password);
}
}
}
return dataSource;