继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

使用jsoup和httpClient爬取慕课网的课程信息

yanrun
关注TA
已关注
手记 1
粉丝 63
获赞 42

最近人工智能,大数据,机器学习可谓火的一塌糊涂,不懂点AI出门都不好意思和别人打招呼,而人工智能的基础是海量的数据,而爬虫是获取互联网数据的一把利器,最近正好在学习爬虫,就用jsoup+httpClient写了一个爬取慕课网java课程信息的爬虫,希望能帮助到有需要的小伙伴。

  • 什么是jsoup
    根据百度百科

jsoup 是一款Java 的HTML解析器,可直接解析某个URL地址、HTML文本内容。它提供了一套非常省力的API,可通过DOM,CSS以及类似于jQuery的操作方法来取出和操作数据。

jsoup和解析xml的dom4j, 解析json的gson非常类似,可以理解为有了它就可以获取HTML文档中的内容了。
闲话少说,进入正题
先来看看要获取内容的网页是什么样子的:
慕课网java课程列表
目前java课程总共有5页,第一页的URL是这个样子的https://www.imooc.com/course/list?c=java
点击第二页,URL变为了https://www.imooc.com/course/list?c=java&page=2
第三页的URL为https://www.imooc.com/course/list?c=java&page=3,可以看到https://www.imooc.com/course/list?c=java&page= 这段是固定的只需要更换页码就可以实现翻页,我们只需要循环访问每一页,然后解析获得到的HTML文件就可以实现爬取课程信息了。
Talk is cheap, show you the code.
图片描述
创建Maven工程导入依赖的部分我就不写,有需要的小伙伴可以先自行学习下。
首先看一下我们都能获取到那些信息
使用浏览器的开发者模式查看网页源码:

<div class="course-card-container">
    <a target="_blank" href="/learn/678" class="course-card">
                    <div class="course-rate"><i class="icon-check"></i></div>

        <div class="course-card-top">
            <img class="course-banner lazy" data-original="//img4.mukewang.com/5775e9cb00013c9606000338-240-135.jpg" src="//img4.mukewang.com/5775e9cb00013c9606000338-240-135.jpg" style="display: inline;">
                        <div class="course-label">
                                                <label>Java</label>
                                            </div>
                    </div>
        <div class="course-card-content">
            <h3 class="course-card-name">Servlet+Ajax实现搜索框智能提示</h3>
            <div class="clearfix course-card-bottom">
                <div class="course-card-info">
                    <span>中级</span><span><i class="icon-set_sns"></i>26855</span>
                </div>
                <p class="course-card-desc">Java实现搜索框智能提示,熟练掌握使用Servlet和Ajax</p>
            </div>
        </div>
    </a>
</div>

可以看到能够获取的信息有课程名称,课程的链接地址,图片地址,等级,标签,简介和学习的人数,据此我们可以建立相应的实体类:

public class ImoocCourse {

    private String imgSrc; //课程图片地址
    private String courseURL; //课程连接
    private String courseName; //课程名称
    private String courseLevel; //课程等级
    private List<String> courseLabels; //课程标签
    private String courseDesc; //课程简介
    private String studyNum; //学习人数
    //省略构造方法和getter,setter
}

然后在分析一下网页的结构,可以看到课程列表是在一个class为container的div中而每门课的信息又是在class为course-card-container的div中,这样就有了爬取的大致思路即获取container部分的数据,然后循环获取其中的每个course-card-container中的数据。此外还有一个非常重要的部分即分析页码部分获取总页数,页码部分的源码如下:

<div class="page"><a href="/course/list?c=java&page=1">首页</a><a href="/course/list?c=java&page=1">上一页</a><a class="text-page-tag" href="/course/list?c=java&page=1">1</a><a href="javascript:void(0)" class="active text-page-tag">2</a><a class="text-page-tag" href="/course/list?c=java&page=3">3</a><a class="text-page-tag" href="/course/list?c=java&page=4">4</a><a class="text-page-tag" href="/course/list?c=java&page=5">5</a><a href="/course/list?c=java&page=3">下一页</a><a href="/course/list?c=java&page=5">尾页</a></div>
            </div>

可以通过获取最后一个a标签的href属性中的page值来获取总页数。
分析完毕就可以请出httpClient来帮我们获取网页的信息了。
使用httpClient获取网页的源码

public String sendHttpGet(String url) {
        String responseContent = null;
        CloseableHttpClient httpClient = null;
        CloseableHttpResponse response = null;
        try {
            HttpGet httpGet = new HttpGet(url);
            httpClient = HttpClients.createDefault();
            response = httpClient.execute(httpGet);
            HttpEntity entity = response.getEntity();
            responseContent = EntityUtils.toString(entity, "UTF-8");
        } catch(Exception e) {
            e.printStackTrace();
            return "";
        } finally {
            try {
                if(null != response) {
                    response.close();
                }
                if(null != httpClient) {
                    httpClient.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return responseContent;
    }

获取完毕使用jsoup来分析网页:
jsoup需要先创建一个Document对象, Document是一个装载html的文档类,可以把它看作是整个html文档。

Document doc = Jsoup.parse(htmlString); //htmlString就是使用httpClient获取的网页源码

jsoup可以使用类似于jQuery的选择器来对文档进行处理非常方便,例如获取class为java的元素可以使用doc.select(".java"); 或doc.getElementsByClass("java");还可以使用doc.getElementsByTag("a");来获取a标签,使用attr方法来获取标签的属性值,使用text方法获取内容等等就不一一赘述了。
解析文档获取总页数:

private int getLastEqualsIndex(String str) {
        return str.lastIndexOf("=") + 1;
    }

private int getTotalPageNum() {
        try {
            Element lastPageElement = doc.select(".page a").last();
            lastPageElement.getElementsByClass("active text-page-tag");
            String lastPageHref = (lastPageElement.getElementsByClass("active text-page-tag").size() == 0) 
                    ? doc.select(".page a").last().attr("href") : lastPageElement.text();
            return Integer.parseInt(lastPageHref.substring(getLastEqualsIndex(lastPageHref)));
        } catch(Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

剩下的工作就是拼接URL循环访问每一页,然后分别解析每一页的内容了,这部分和解析页码非常类似就不详细写出了。
拿到数据后就可以进行数据分析了,比如分析各个等级课程的占比,定时爬取来分析学习人数的变化等等。爬虫还涉及到了很多知识,感兴趣的小伙伴可以深入研究一下。这篇文章就到此结束了,感谢收看。

  • 后记
    由于爬虫在短时间内大量的访问服务器会在一定程度上增加网站服务器的压力,因此很多网站比如天猫,美团等都做了反爬措施,在此还是要感谢慕课网没有对爬虫说不。
    我把完整的代码放在了https://github.com/runyan/imoocCrawler ,里面用了一些奇淫巧技,感兴趣可以去看看,有问题欢迎提issues进行交流。
打开App,阅读手记
10人推荐
发表评论
随时随地看视频慕课网APP

热门评论

大师  上班请祭出你的神兽放公司的代码里

说!大师兄为毛要搞爬虫了!

查看全部评论