网站开发的现状研究,今天国际大事新闻,网络营销推广的研究方向,网页设计图片跟随鼠标移动转载自 Jsoup代码解读之七-实现一个CSS Selector当当当#xff01;终于来到了Jsoup的特色#xff1a;CSS Selector部分。selector也是我写的爬虫框架webmagic开发的一个重点。附上一张street fighter的图#xff0c;希望以后webmagic也能挑战Jsoup!
select机制
Jsoup的se…转载自 Jsoup代码解读之七-实现一个CSS Selector当当当终于来到了Jsoup的特色CSS Selector部分。selector也是我写的爬虫框架webmagic开发的一个重点。附上一张street fighter的图希望以后webmagic也能挑战Jsoup!
select机制
Jsoup的select包里类结构如下在最开始介绍Jsoup的时候就已经说过NodeVisitor和Selector了。Selector是select部分的对外facade而NodeVisitor则是遍历树的底层APICSS Selector也是根据NodeVisitor实现的遍历。
Jsoup的select核心是Evaluator。Selector所传递的表达式会经过QueryParser最终编译成一个Evaluator。Evaluator是一个抽象类它只有一个方法
!-- lang: java --
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中贴一下代码了
!-- lang: java --
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要好得多了基本每个类都对应一个真实的概念抽象可能以后会在这方面下点工夫。
下篇文章将讲最后一部分白名单及HTML过滤机制。
最后依然附上这系列文章和代码的github地址https://github.com/code4craft/jsoup-learning