【爬虫】Jsoup实现WebHunter手动爬虫模块          返回主页

本文是WebHunter手动爬虫模块的技术实现小结,关于该项目的演示请参考另一篇博文

WebHunter新闻爬虫系统介绍

工程结构

    --com.hunter.dao            数据访问类包
        --HunterDao.java            DAO接口,声明数据持久化方法
        --HunterDaoImpl.java        DAO接口实现类,数据持久化方法实现
    --com.hunter.global     全局类包
        --GlobalVariable.java   全局变量声明类
    --com.hunter.service        路由及业务逻辑层
        --HunterIndex.java      主页路由
        --URLPaser.java         页面解析逻辑,参数解析
    --com.hunter.util       工具类包
        --DBUtils.java          数据库访问工具类
        --JsoupUtils.java       Jsoup工具类,页面内容解析核心类

工作原理

代码结构及运行原理

1. HunterIndex作为首页路由在程序运行时加载,并加载首页
2. 从页面传来url被URLPaser解析
3. url如果正确则被传入JsoupUtils中,通过对应的方法分别取出文章题目及文章正文;
4. 前面的数据正确取出之后再传入dao层持久化。
5. 持久化成功/失败会记录到requst中并返回到首页。

查看效果

在另一展示应用中可添加数据库访问逻辑并将对应的数据加载到页面上。
这样便做到了数据采集和展示分离。

代码总体结构

HunterIndex->URLPaser->JsoupUtils->Dao->HunterIndex

代码解析

URLPaser.java

public class URLPaser extends HttpServlet {
    ..........
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding("UTF-8");
        response.setCharacterEncoding("UTF-8");
        response.setContentType("text/html;charset=UTF-8");
        //获取参数
        String url = request.getParameter("url");
        System.out.println(url);
        //传入参数进行处理,解析对应的内容
        String articleTitle = JsoupUtils.getArticleTitle(url);
        String articleContent = JsoupUtils.getArticleContent(url);
        //持久化数据
        hunterDao = new HunterDaoImpl();
        Boolean flag = hunterDao.saveData(articleTitle, new Date(System.currentTimeMillis()), articleContent);
        //判断返回结果进行请求转发
        if (flag == true) {
            request.setAttribute("message", "数据添加成功,请继续添加");
            request.getRequestDispatcher("HunterIndex").forward(request, response);
        } else {
            request.setAttribute("message", "数据添加失败,请核对url是否正确");
            request.getRequestDispatcher("HunterIndex").forward(request, response);
        }
    }
    ......省略doPost()方法.......

}

解释: 1. 前台传来一个url字符串,在本文件拿到之后分别对其进行题目和文本正文的抽取;

  1. 将解析出的字符串进行dao层调用,将数据持久化;

  2. 添加成功或失败均会回到主页,并将结果信息一并送回,作为标记使使用者进一步添加或修正错误。

JsoupUtils.java

public class JsoupUtils {
    private static String title;
    private static Document docs;
    private static String articleContent;
    /**
     * 返回文章标题
     * @param url
     * @return title
     */
    public static String getArticleTitle(String url) {
        try {
            docs = Jsoup.connect(url).timeout(3000)           // 设置连接超时时间
                    .get();
            //文章标题
            Elements articleTitle = docs.select("#C-Main-Article-QQ > div.hd > h1");
            for (Element element : articleTitle) {
                title = element.html();
            }
        } catch (Exception e) {
            System.out.println("没有发现内容");
        }
        return title;
    }

    public static String getArticleContent(String url) {
        try {
            docs = Jsoup.connect(url).timeout(3000)           // 设置连接超时时间
                    .get();
            //正文html
            Element contentHtml = docs.getElementById("Cnt-Main-Article-QQ");
            articleContent = contentHtml.html();
        } catch (Exception e) {
            System.out.println("没有发现内容");
        }
        return articleContent;
    }
}

解释: 1. 本类是应用的核心逻辑,可以说其余的类/包均是为其服务的。

  1. 在该类中通过CSS选择器及页面元素id进行具体的html代码段的抽取

  2. 通过Jsoup 的connect()获取一个url链接并获取其页面文档内容返回一个Document实例 docs = Jsoup.connect(url).timeout(3000).get(); // 设置连接超时时间

  3. 通过docs.getElementById()方法获取对应ID内容,docs.select()接受一个css选择器字符串,两者作用相同,均为从html文档中提取对应的内容 //正文html Element contentHtml = docs.getElementById("Cnt-Main-Article-QQ");

  4. 通过Element的html()方法将抽取的内容返回即可,返回值为String方便持久化或者其他操作。 articleContent = contentHtml.html();

小结

本文讲解了基于Jsoup的页面抓取工具的运行机理,Jsoup的强大的页面解析功能能够方便使用者很容易的抓取

到想要的内容,不愧为Java界的页面解析“瑞士军刀”。

                                                                                            --7.28