Jsoup代码解读之七-实现一个CSS Selector

当当当!终于来到了Jsoup的特色:CSS Selector部分。selector也是我写的爬虫框架webmagic开发的一个重点。附上一张street fighter的图,希望以后webmagic也能挑战Jsoup!

select机制

Jsoup的select包里,类结构如下:

在最开始介绍Jsoup的时候,就已经说过NodeVisitorSelector了。Selector是select部分的对外facade,而NodeVisitor则是遍历树的底层API,CSS Selector也是根据NodeVisitor实现的遍历。

Jsoup的select核心是Evaluator。Selector所传递的表达式,会经过QueryParser,最终编译成一个EvaluatorEvaluator是一个抽象类,它只有一个方法:


public abstract boolean matches(Element root, Element element);

注意这里传入了root,是为了某些情况下对树进行遍历时用的。

Evaluator的设计简洁明了,所有的Selector表达式单词都会编译到对应的Evaluator。例如#xx对应Id.xx对应Class[]对应Attribute。这里补充一下w3c的CSS Selector规范:http://www.w3.org/TR/CSS2/selector.html

当然,只靠这几个还不够,Jsoup还定义了CombiningEvaluator(对Evaluator进行And/Or组合),StructuralEvaluator(结合DOM树结构进行筛选)。

这里我们可能最关心的是,“div ul li”这样的父子结构是如何实现的。这个的实现方式在StructuralEvaluator.Parent中,贴一下代码了:


static class Parent extends StructuralEvaluator {
    public Parent(Evaluator evaluator) {
        this.evaluator = evaluator;
    }

    public boolean matches(Element root, Element element) {
        if (root == element)
            return false;

        Element parent = element.parent();
        while (parent != root) {
            if (evaluator.matches(root, parent))
                return true;
            parent = parent.parent();
        }
        return false;
    }
}

这里Parent包含了一个evaluator属性,会根据这个evaluator去验证所有父节点。注意Parent是可以嵌套的,所以这个表达式"div ul li"最终会编译成And(Parent(And(Parent(Tag("div")),Tag("ul")),Tag("li")))这样的Evaluator组合。

select部分比想象的要简单,代码可读性也很高。经过了parser部分的研究,这部分应该算是驾轻就熟了。

关于webmagic的后续打算

webmagic是一个爬虫框架,它的Selector是用于抓取HTML中指定的文本,其机制和Jsoup的Evaluator非常像,只不过webmagic暂时是将Selector封装成较简单的API,而Evaluator直接上了表达式。之前也考虑过自己定制DSL来写一个HTML,现在看了Jsoup的源码,实现能力算是有了,但是引入DSL,实现只是一小部分,如何让DSL易写易懂才是难点。

其实看了Jsoup的源码,精细程度上比webmagic要好得多了,基本每个类都对应一个真实的概念抽象,可能以后会在这方面下点工夫。

Jsoup代码解读之五-实现一个CSS Selector的更多相关文章

  1. Jsoup代码解读之一-概述

    Jsoup代码解读之一-概述 今天看到一个用python写的抽取正文的东东,美滋滋的用Java实现了一番,放到了webmagic里,然后发现Jsoup里已经有了…觉得自己各种不靠谱啊!算了,静下心来学 ...

  2. Jsoup代码解读之二-DOM相关对象

    Jsoup代码解读之二-DOM相关对象   之前在文章中说到,Jsoup使用了一套自己的DOM对象体系,和Java XML API互不兼容.这样做的好处是从XML的API里解脱出来,使得代码精炼了很多 ...

  3. Jsoup代码解读之六-防御XSS攻击

    Jsoup代码解读之八-防御XSS攻击 防御XSS攻击的一般原理 cleaner是Jsoup的重要功能之一,我们常用它来进行富文本输入中的XSS防御. 我们知道,XSS攻击的一般方式是,通过在页面输入 ...

  4. Jsoup代码解读之四-parser

    Jsoup代码解读之四-parser 作为Java世界最好的HTML 解析库,Jsoup的parser实现非常具有代表性.这部分也是Jsoup最复杂的部分,需要一些数据结构.状态机乃至编译器的知识.好 ...

  5. Jsoup代码解读之三-Document的输出

    Jsoup代码解读之三-Document的输出   Jsoup官方说明里,一个重要的功能就是output tidy HTML.这里我们看看Jsoup是如何输出HTML的. HTML相关知识 分析代码前 ...

  6. 如何判断一个DOM元素正在动画,一个CSS“阻塞”JS的例子

    一般情况下CSS不会直接影响JS的程序逻辑,但是以CSS实现动画的话,这个便不太确定了,这个故事发生在与UED迁移全局样式的过程. 曾经我有一段实现弹出层隐藏动画的代码是这个样子的: if (this ...

  7. 转:Selenium之CSS Selector定位详解

    CSS selector定位 CSS(Cascading Style Sheets)是一种语言,它被用来描述 HTML 和 XML 文档的样式.  百度输入框: <input name=&quo ...

  8. css selector

    文章一: http://www.jb51.net/css/68287.html 去年我学jQuery的时候,曾经做过一点选择器(selector)的笔记,今天是CSS的选择器,以后还有一部分xPath ...

  9. Xpath 和Css Selector使用

    Xpath是xml的路径语言,就是通过元素的路径来查找标签元素. Xpath直接在火狐浏览器的firebug中练习,49版本一下的火狐才能用firebug插件. Xpath的使用方法 注://*    ...

随机推荐

  1. mfc分个窗口,设置分割条不可移动

    最近要做一个项目,做界面时遇到了这个问题,找了好多资料,终于解决了,在此记录一下,希望对有需要的人有所帮助.好了,不多说了,具体的处理如下: 新建一个类CFixSplitterWnd继承CSplitt ...

  2. C-JAVA 论坛

    http://www.cnblogs.com/lpjia/ JAVA黑马 http://java.itheima.com/java/service/javacourse.shtml

  3. leetcode Search Insert Position Python

    #Given a sorted array and a target value, return the index if the target is found. If #not, return t ...

  4. Oracle学习之Oracle 树操作(select…start with…connect by…prior)

    转自:http://www.cnblogs.com/linjiqin/archive/2013/06/24/3152674.html oracle树查询的最重要的就是select…start with ...

  5. 【Howie玩docker】-windows下玩docker

    Windows下安装toolbox一直没成功,于是投机取巧,用虚拟机手工打造玩docker的方法. 步骤: 安装虚拟机,安装centos 在win下建立共享文件夹,假如是 f:/share 在cent ...

  6. mini-httpd源码分析-version.h

    /* version.h - version defines for mini_httpd */ #ifndef _VERSION_H_ #define _VERSION_H_ #define SER ...

  7. Activity之间定时跳转

    起源:很多应用在打开时,首先会加载欢迎页面,经过几秒后再跳转到主页面. 下面,我通过两种不同的方式来实现页面的定时跳转. 第一种方式: 通过Timer类的schedule方法. 实现从MainActi ...

  8. 如何使Label带有链接??此法感觉有点取巧!!!

    关键代码 /**************************************************************第一行***************************** ...

  9. HTML 5 drag and drop 简介

    Html 5 drag and drop 简介 HTML5提供了专门拖拽和拖放的API draggable属性 启用拖拽 draggable属性是否可被拖拽, 可选值: true, false, au ...

  10. java文件读写操作

    Java IO系统里读写文件使用Reader和Writer两个抽象类,Reader中read()和close()方法都是抽象方法.Writer中 write(),flush()和close()方法为抽 ...