JsoupXpath

Build Status GitHub release Maven License

A html parser with xpath base on Jsoup and Antlr4.Maybe it is the best in java,Just try it.

English Doc

简介

JsoupXpath 是一款纯Java开发的使用xpath解析提取html数据的解析器,针对html解析完全重新实现了W3C XPATH 1.0标准语法,xpath的Lexer和Parser基于Antlr4构建,html的DOM树生成采用Jsoup,故命名为JsoupXpath. 为了在java里也享受xpath的强大与方便但又苦于找不到一款足够好用的xpath解析器,故开发了JsoupXpath。JsoupXpath的实现逻辑清晰,扩展方便, 支持完备的W3C XPATH 1.0标准语法,W3C规范:http://www.w3.org/TR/1999/REC-xpath-19991116 ,JsoupXpath语法描述文件Xpath.g4

Change Log

https://github.com/zhegexiaohuozi/JsoupXpath/releases

社区讨论

大家有什么问题或建议现在都可以选择通过下面的邮件列表讨论,首次发言前需先订阅并等待审核通过(主要用来屏蔽广告宣传等)

快速开始

maven依赖,全版本请参见release信息中央maven库

<dependency>
   <groupId>cn.wanghaomiao</groupId>
   <artifactId>JsoupXpath</artifactId>
   <version>2.3.2</version>
</dependency>

示例:

String html = "<html><body><script>console.log('aaaaa')</script><div class='test'>some body</div><div class='xiao'>Two</div></body></html>";
JXDocument underTest = JXDocument.create(html);
String xpath = "//div[contains(@class,'xiao')]/text()";
JXNode node = underTest.selNOne(xpath);
Assert.assertEquals("Two",node.asString());

其他可以参考 org.seimicrawler.xpath.JXDocumentTest,这里有大量的测试用例

或者Issue中比较典型的例子

语法

支持完备的W3C XPATH 1.0标准语法,W3C规范:http://www.w3.org/TR/1999/REC-xpath-19991116

这里是JsoupXpath的基于Antlr4的语法解析树示例,方便大家更快速的一览JsoupXpath的语法处理能力与语法解析执行过程

关于使用Xpath的一些注意事项

多数情况下是不建议直接粘贴Firefox或chrome里生成的Xpath,这些浏览器在渲染页面会根据标准自动补全一些标签,如table标签会自动加上tbody标签,这样生成的Xpath路径显然不是最通用的,所以很可能就取不到值。所以,要使用Xpath并感受Xpath的强大以及他所带来便捷与优雅最好就是学习下Xpath的标准语法,这样应对各种问题才能游刃有余,享受Xpath的真正威力!

函数

开发者添加函数

以上只是Xpath1.0标准中的函数,开发亦可以方便快捷的添加自定义函数,只需实现 org.seimicrawler.xpath.core.Function.java接口,并在你的系统初始化的时候调用Scanner.registerFunction(Class<? extends Function> func),不需要修改语法范式,JsoupXpath运行时即可识别并加载。对于标准语法中目前JsoupXpath还未实现的函数,欢迎大家向主仓库提交Pull request,一起添砖添瓦。

NodeTest

AxisName:  'ancestor'         //在当前上下文中节点的祖先中选择
  |  'ancestor-or-self'       //在当前上下文中节点的祖先及包括自身中选择
  |  'attribute'              //标记做提取节点属性运算
  |  'child'                  //在当前上下文中节点的子节点中选择 这是xpath默认的轴,如 /div/li 就是 /div/child::li 的简写
  |  'descendant'             //在当前上下文中节点的后代中选择
  |  'descendant-or-self'     //在当前上下文中节点的后代包括自身中选择
  |  'following'              //在当前上下文中节点后面的全部节点中选择
  |  'following-sibling'      //在当前上下文中节点后面的全部同胞节点中选择
  |  'parent'                 //在当前上下文中节点的父亲节点中选择
  |  'preceding'              //在当前上下文中节点前面的全部节点中选择
  |  'preceding-sibling'      //在当前上下文中节点前面的全部同胞节点中选择
  |  'self'                   //当前上下文中选择
  |  'following-sibling-one'  //在上下文中节点的前一个同胞节点中选择(JsoupXpath扩展)
  |  'preceding-sibling-one'  //在上下文中节点的下一个同胞节点选择(JsoupXpath扩展)
  |  'sibling'                //全部同胞(JsoupXpath扩展)(开发中。。。)
  ;

操作符

MINUS
       :  '-';
  PLUS
       :  '+';
  DOT
       :  '.';
  MUL
       : '*';
  DIVISION
       : '`div`';
  MODULO
       : '`mod`';
  DOTDOT
       :  '..';
  AT
       : '@';
  COMMA
       : ',';
  PIPE
       :  '|';
  LESS
       :  '<';
  MORE_
       :  '>';
  LE
       :  '<=';
  GE
       :  '>=';
  START_WITH
       :  '^=';  // `a^=b` 字符串a以字符串b开头 a startwith b  (JsoupXpath扩展)
  END_WITH
       :  '$=';  // `a*=b` a包含b, a contains b   (JsoupXpath扩展)
  CONTAIN_WITH
       :  '*=';  // a包含b, a contains b  (JsoupXpath扩展)
  REGEXP_WITH
       :  '~=';  // a的内容符合 正则表达式b   (JsoupXpath扩展)
  REGEXP_NOT_WITH
       :  '!~';  //a的内容不符合 正则表达式b   (JsoupXpath扩展)

应用的项目

目前JsoupXpath被大量使用的项目或是组织有:SeimiCrawler。 如果您也有项目在使用JsoupXpath,并希望出现在这个列表中,可以通过下面的联系方式联系我,邮件格式可以为:

项目或组织名称:XX
项目或组织URL:http://xxx.xxx.cc