转载自    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是一个抽象类,它只有一个方法:

<!-- 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

Jsoup代码解读之七-实现一个CSS Selector相关推荐

  1. jsoup获得css,Jsoup代码解读之五-实现一个CSS Selector

    Jsoup代码解读之七-实现一个CSS Selector 当当当!终于来到了Jsoup的特色:CSS Selector部分.selector也是我写的爬虫框架webmagic开发的一个重点.附上一张s ...

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

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

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

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

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

    转载自   Jsoup代码解读之三-Document的输出 Jsoup官方说明里,一个重要的功能就是***output tidy HTML***.这里我们看看Jsoup是如何输出HTML的. HTML ...

  5. Jsoup代码解读之四-parser(上)

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

  6. Jsoup代码解读之五-parser(中)

    转载自    Jsoup代码解读之五-parser(中) 上一篇文章讲到了状态机和词法分析的基本知识,这一节我们来分析Jsoup是如何进行词法分析的. 代码结构 先介绍以下parser包里的主要类: ...

  7. Jsoup代码解读之六-parser(下)

    转载自   Jsoup代码解读之六-parser(下) 最近生活上有点忙,女儿老是半夜不睡,精神状态也不是很好.工作上的事情也谈不上顺心,有很多想法但是没有几个被认可,有些事情也不是说代码写得好就行的 ...

  8. css游戏代码_介绍CSSBattle-第一个CSS代码搜寻游戏

    css游戏代码 by kushagra gour 由kushagra gour 介绍CSSBattle-第一个CSS代码搜寻游戏 (Introducing CSSBattle - the first ...

  9. Python 中 xpath 语法 与 lxml 库解析 HTML/XML 和 CSS Selector

    The lxml.etree Tutorial :https://lxml.de/tutorial.html python3 解析 xml:https://www.cnblogs.com/deadwo ...

最新文章

  1. ImportError: No module named _tkinter, please install the python-tk package ubuntu运行tkinter错误
  2. 关于项目重构,知道真相的程序员眼泪笑了出来
  3. mysql 百度地图插件_GitHub - huizhong/grafana-baidumap-panel: Grafana 百度地图插件
  4. nusoap php 7,nusoap-用php的NuSoap 访问webservice遇到的问题。
  5. python plt.plot bar 设置绘图尺寸大小
  6. 移动开发解决方案之玩转输入框
  7. python基础语法(一)
  8. Zigbee学习计划暂停
  9. 2018-2019-1 20165320 《信息安全系统设计基础》第八周学习总结
  10. mysql函数commit_phpmysqli_commit()函数和mysqli_autocommit()函数比较
  11. split函数 在oracle,oracle的split函数
  12. Windows及Linux系统下--adb驱动安装及问题总结
  13. 蓝牙协议分析工具Wireshark/Frontline/Ellisys的使用
  14. 小程序中自定义图片预览功能
  15. linux给文件夹加密码,如何使用linux命令给文件上锁?linux命令文件加密方法
  16. win7啊,我的纠结,ip啊
  17. uni app 零基础小白到项目实战-1
  18. 组织结构图插件_一个简单直接的组织结构图插件
  19. linux c语言 ppt,Linux下C语言编程.ppt
  20. 连续两年蝉联冠今Topday“2015年度优秀供应商”

热门文章

  1. 40. 组合总和 II021(回溯法)
  2. C++未定义行为-数组越界
  3. android 语音助手官网,breeno语音助手最新版
  4. c语言case怎么输入字母,如何使用switch case语句将字母转换为数字
  5. 数据结构---模式匹配
  6. 2019-03-18-算法-进化(实现strStr())
  7. Educational Codeforces Round 76 (Rated for Div. 2) F. Make Them Similar 折半搜索
  8. 【NOI2019】回家路线【无后效性dp状态设计】【斜率优化】
  9. P2480 [SDOI2010]古代猪文(数论好题)
  10. HDU - 2204 Eddy‘s爱好(尚未完全解决)