Jsoupxpath 使用 xpath 解析 html 的解析器开源项目

我要开发同款
匿名用户2015年10月22日
57阅读
开发技术Java
所属分类Web应用开发、HTML解析器
授权协议Apache

作品详情

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

快速开始

maven依赖:

   cn.wanghaomiao   JsoupXpath   ${latest-release-version}

示例:

String xpath="//div[@id='post_list']/div[./div/div/span[@class='article_view']/a/num()>1000]/div/h3/allText()";String doc = "...";JXDocument jxDocument = new JXDocument(doc);Listrs = jxDocument.sel(xpath);for (Object o:rs){if (o instanceof Element){int index = ((Element) o).siblingIndex();System.out.println(index);}System.out.println(o.toString());}

 

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

 

语法

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

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

//ul[@class='subject-list']/li[./div/div/span[@class='pl']/num()>(1000+90*(2*50))][last()][1]/div/h2/allText() 这个主要是一些表达式嵌套的解析示例,点击图片可以查看大图 

//ul[@class='subject-list']/li[not(contains(self::li/div/div/span[@class='pl']//text(),'14582'))]/div/h2//text()这个是对内置函数支持的一个解析示例,点击图片可以查看大图 

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

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

函数

intposition() 返回当前节点在其所在上下文中的位置

intlast() 返回所在上下文的最后那个节点位置

intfirst() 返回所在上下文的的第一个节点位置

stringconcat(string,string,string*) 连接若干字符串

booleancontains(string,string) 判断第一个字符串是否包含第二个

intcount(node-set) 计算给定的节点集合中节点个数

booleanstarts-with(string,string) 判断第一个字符串是否以第二个开头

intstring-length(string?) 如果给定了字符串则返回字符串长度,如果没有,那么则将当前节点转为字符串并返回长度

stringsubstring(string,number,number?) 第一个参数指定字符串,第二个指定起始位置(xpath索引都是从1开始),第三指定要截取的长度,这里要注意在xpath的语法里这,不是结束的位置。

substring("12345",1.5,2.6)returns"234"

substring("12345",2,3)returns"234"

stringsubstring-ex(string,number,number) 第一个参数指定字符串,第二个指定起始位置(java里的习惯从0开始),第三个结束的位置(支持负数),这个是JsoupXpath扩展的函数,方便java习惯的开发者使用。

stringsubstring-after(string,string) 在第一个字符串中截取第二个字符串之后的部分

stringsubstring-before(string,string) 在第一个字符串中截取第二个字符串之前的部分

开发者添加函数

以上只是Xpath1.0标准中的函数,开发亦可以方便快捷的添加自定义函数,只需实现 org.seimicrawler.xpath.core.Function.java接口并且包路径为packageorg.seimicrawler.xpath.core.function;即可,不需要修改语法范式,JsoupXpath运行时即可自动识别并加载(并不一定非要在一个jar中)。对于标准语法中目前JsoupXpath还未实现的函数,欢迎大家向主仓库提交Pullrequest,一起添砖添瓦。

NodeTest

allText()提取节点下全部文本,取代类似 //div/h3//text()这种递归取文本用法

html()获取全部节点的内部的html

outerHtml()获取全部节点的包含节点本身在内的全部html

num()抽取节点自有文本中全部数字,如果知道节点的自有文本(即非子代节点所包含的文本)中只存在一个数字,如阅读数,评论数,价格等那么直接可以直接提取此数字出来。如果有多个数字将提取第一个匹配的连续数字。

text() 提取节点的自有文本

node() 提取所有节点

轴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       :  '=';  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扩展)
查看全文
声明:本文仅代表作者观点,不代表本站立场。如果侵犯到您的合法权益,请联系我们删除侵权资源!如果遇到资源链接失效,请您通过评论或工单的方式通知管理员。未经允许,不得转载,本站所有资源文章禁止商业使用运营!
下载安装【程序员客栈】APP
实时对接需求、及时收发消息、丰富的开放项目需求、随时随地查看项目状态

评论