爬虫项目Java

本文介绍了一个使用Java实现的GitHub项目爬虫,目标是收集awesome-java项目中提到的所有GitHub项目的活跃度信息,包括star,fork,open_issue。文章详细阐述了爬虫的实现过程,从获取页面内容、解析页面结构、通过GitHub API获取项目信息,到存储数据到MySQL数据库,并展示了如何通过多线程优化爬取效率,以及如何设置Linux定时任务来每日更新数据。
摘要由CSDN通过智能技术生成

什么是爬虫?

爬虫就是一个HTTP客户端。当我们在浏览器地址栏输入一个URL时,浏览器就会给服务器发送一个HTTP请求,服务器接收到后会返回给浏览器一个HTTP响应。爬虫就是根据需要构造请求,并且再根据需要简单的解析一下响应数据。爬虫的优势就是可以根据需要批量的获取数据。

爬取的数据

爬取的是GitHub上项目的一些具体信息。例如:star,fork,open_issue。
然后收集这些项目的这些属性,衡量出这些项目中哪些是比较活跃/流行的。

项目最终需求

给awesome-java 这个项目中提到的所有的GitHub上的项目按照活跃程度排次序

整个项目的框架

在这里插入图片描述

核心工作

1.需要获取到所有待收集信息的项目列表--------基于OkHttpClient
2.遍历项目列表,一次获取到每个项目的主页信息,进一步就可以知道该项目的star,fork,open_issue--------基于Jsoup
3.把这些数据存储到数据库中--------基于MySQL
4.写一个简单网页/服务器,来展示数据库中的数据(通过图表的形式来呈现)

工作1——获取到所有待收集信息的项目列表

在这里插入图片描述
使用爬虫程序,获取到https://github.com/akullpp/awesome-java/blob/master/README.md这个页面的内容,进而就能知道所有的项目链接信息。
在这里插入图片描述
ul表示无序列表,li表示列表中的一个项,a表示超链接,a标签里的href表示链接要跳转到哪个页面。
通过分析页面结构,看到入口页面中包含很多ul,每个ul中又有很多的a标签,a标签中href属性里的url就是我们想要获取的内容。

如何获取到页面内容

构造一个HTTP请求发送给服务器即可。
通过使用OKHttp库,就能根据指定的URL获取到对应页面的内容.内容一般是一个html结构的内容。

public String getPage(String url) throws IOException {
   
        //1.创建一个 OkHttpClient 对象
        okHttpClient = new OkHttpClient();

        //2.创建一个 Request 对象
        //builder 这个类是一个辅助创造 Request 对象的类
        // Builder 中提供的 url 方法能够设定当前请求的 url
        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.printf("请求失败");
            return null;
        }
        return response.body().string();

    }

如何分析页面结构

通过使用 Jsoup 库来分析网页结构,先获取所有的 li 标签。(里面混杂了一些li 标签,但是他并不是项目的内容),再获取 li 标签中的 a 标签 ,然后获取 href 的内容。存储到一个 Project 类中。

public List<Project> parseProjectList(String html) {
   
        ArrayList<Project> result = new ArrayList<>();
        Document document = Jsoup.parse(html);
        Elements elements = document.getElementsByTag("li");
        for (Element li : elements) {
   
            Elements allLink = li.getElementsByTag("a");
            if (allLink.size() == 0) {
   
                //当前 li 标签没有包含 a 标签
                //就直接忽略
                continue;
            }
            Element link = allLink.get(0);

            String url = link.attr("href");
            if (!url.startsWith("https://github.com")) {
   
                continue;
            }
            if (urlBlackList.contains(url)) {
   
                continue;
            }

            Project project = new Project();
            project.setName(link.text());
            project.setUrl(link.attr("href"));
            project.setDescription(li.text());
            result.add(project);
        }
        return result;
    }

存储项目的Project类

package dao;

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

@Getter
@Setter
@ToString
public class Project {
   
    //项目名称,对应 a 标签中的内容
    private String name;

    //项目主页链接,对应 a 标签中的 href 属性
    private String url;

    //项目的描述信息,对应到 li 标签里面的内容
    private String description;

    //以下属性都是要统计到的数据
    //需要根据该项目的 url 进入到对应页面,进而统计数据
    private int starCount;
    private int forkCount;
    private int openIssueCount;
}

通过github官方提供的API进行获取到项目的star,fork,open_issue。

通过项目的URL解析出项目仓库的仓库名和作者名

//这个方法的功能,就是把项目的 url 提取出其中的仓库名字和作者名字
    public String getRepoName(String url) {
   
        int lastOne = url.lastIndexOf("/");
        int lastTwo = url.lastIndexOf("/", lastOne - 1);
        if (lastOne == -1 || lastTwo == -1) {
   
            System.out.println("当前url不是一个项目的url! url :" + url);
            return null;
        }
        return url.substring(lastTwo + 1);
    }

然后解析出仓库名和作者名后根据Github广泛提供的API,能得到一个关于此项目的一个JSON格式的文件,通过解析这个文件得到该项目的star,fork,open_issue。

public String getRepoInfo(String respName) throws IOException {
   
        
        String userName = "你的Github用户名";
        String passWord = "你的Github密码";
        //因为github认证后你的爬取数量可以增加
        //进行身份认证,把用户名密码加密之后得到一个字符串, 把这个字符串放到http header中.
        String credential = Credentials.basic(userName, passWord);

        String url = "https://api.github.com/repos/" + respName;

        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("访问Github API失败! URL + " + url);
            return null;
        }
        return response.body().string();
    }

在这里插入图片描述

    //通过这个方法获取到仓库相关信息
    //第一个参数 jsonString 表示获取到的Github API的结果
    //第二个参数 表示将解析的数据存到 project 对象里
    public void parseRepoInfo(String jsonString, Project project) {
   
        Type type = new TypeToken<HashMap<String, Object>>() {
   
        }.getType();

        HashMap<String, Object> hashMap = gson.fromJson(jsonString, type);
        Double starCount = (Double)hashMap.get("stargazers_count");
        project.setStarCount(starCount.
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值