Java 爬虫框架 webmagic 中三种 HTML&XML 页面信息抽取技术解析 -- Xpath & 正则表达式 & CSS选择器
简介:本文详细介绍了用 Java 爬虫框架 webmagic 爬取网站数据的时候,从下载到的 HTML 页面抽取所需信息的三种技术的使用方法:XPath,正则表达式以及 CSS 选择器。
1、XPath
XPath 是一种在 XML 文件中查找信息的语言,它使用路径表达式来选取 XML 文档中的节点或节点集,XPath 也适用于 HTML。为了对XPath的语法进行讲解,我们以下面的HTML案例作为讲解:
<div class="baidu-div">
<table class="baidu-table">
<tr>
<td class="title">
<a class="name" href="https://www.baidu.com" >百度</a>
</td>
<td class="content">
<span id="section1">aaaaa</span>
</td>
</tr>
<tr></tr>
</table>
</div>
1.1 绝对路径与相对路径
XPath 表达式中包含 2 种类型的表达式:相对路径与绝对路径。
首先是绝对路径,绝对路径可以用于直接查找元素,不过弊端就是如果元素路径中有一点儿变动的话,XPath 失效。绝对路径以 “ / ” 开始。
其次是相对路径,相对路径以 " // " 开始,相对路径可以从 XML/HTML DOM 结构的任何位置开始,因此使用相对路径便不需要写很长的 XPath 表达式
我们以 webmagic 框架抽取 HTML 页面的元素为例(此处 page 为封装的 HTML 页面对象),如果我们想获得上面 HTML 文件中 class 属性值为 name 的 a 元素的文本内容,绝对路径写法如下:
String result = page.getHtml().xpath("/div/table/tr[1]/td[1]/a[1]/text()")
result 结果是 “百度”
而相对路径的写法如下:
String result = page.getHtml().xpath("//a[@class='name']/text()")
result 结果是 “百度”
可以看出,对比之下,在 XML/HTML 文档的 DOM 结构很复杂的时候,相对路径写起来比较方便。
1.2 Xpath 简介及常见的基础用法
XPath 中包含 7 种类型的节点,XPath 表达式用于从 XML 文档中选择节点或节点列表。
节点类型 | 节点描述 |
---|---|
root | 根节点 |
element | 元素 |
attribute | 属性 |
text | 文本 |
comment | 注释 |
processing instruction | 处理指令 |
namespace | 命名空间 |
其中,根节点、元素、属性、文本、注释是常见的 XPath 节点类型。下面是从 XML/HTML 文档中选择节点或节点列表的常见表达式。
表达式 | 用法 |
---|---|
nodename | 选取 XML 文件中所有名为 nodename 的元素 |
* | 选取当前页面的所有子元素 |
. | 选取当前节点 |
.. | 选取当前节点的父节点 |
/ | 从根节点开始 |
//node | 选择整个文件中的所有 node 元素 |
nodeA/nodeB | 对于每一个 nodeA 节点, 将其子节点中的所有 nodeB 节点添加到匹配结果中 |
nodeA//nodeB | 对于每一个 nodeA 节点, 将其后代节点中的所有 nodeB 节点添加到匹配结果中 |
@attr | 选取属性 attr |
@* | 选取所有属性 |
text() | 选取节点的文本 |
last() | 选择最后一个节点 |
node[expr] | 选择满足条件表达式 expr 的 node 节点 |
node[number] | 选择第 number 个 node 节点(number 是数字) |
下面结合下面的 HTML ,用几个案例来说明 XPath 的用法。
<div class="baidu-div">
<table class="baidu-table">
<tr>
<td>
<a class="name" href="https://www.baidu.com" value="baidu" >百度</a>
<a class="name" href="https://www.baidu.com" value="use-baidu" >百度一下</a>
</td>
<td class='content'>
<span>11111</span>
<span>22222</span>
<span>33333</span>
</td>
</tr>
<tr></tr>
</table>
</div>
- 案例 1
String result = page.getHtml().xpath("//td[@class='content']/span[last()-1]/text()")
查找 class 属性为 content 的 td 元素下的倒数第二个 span 元素的文本内容,结果是:22222
- 案例 2
String result = page.getHtml().xpath("//table[@class='baidu-table']/tr[1]/td[1]/[a2]/@value")
查找 class 属性为 baidu-table 的 table 元素下的第一个 tr 元素下的第一个 td 元素下的第二个 a 元素的 value属性值,结果为:use-baidu
2、正则表达式&CSS选择器
Webmagic 中用正则表达式抽取元素的函数如下
表达式 | 用法 | 示例 |
---|---|---|
regex(String regex) | 使用正则表达式进行抽取 | |
replace(String regex, String replacement) | 替换内容 |
关于正则表达式,可以参考:学习正则表达式的简单方法
CSS 选择器是与 XPath 类似的元素抽取方式,它在抽取规则相对简单的时候比 XPath 好用,但是如果写复杂一点的抽取规则,就相对要麻烦一点。其抽取函数如下:
表达式 | 用法 | 示例 |
---|---|---|
css(String selector) | 功能同$(),使用Css选择器选择 |
关于CSS表达式,可以参考:CSS 教程
我们根据下面的 HTML 文档,对比一下使用 XPath 、正则表达式和 CSS 选择器抽取元素的区别。
<div class="div-level1">
<table class="div-coding">
<thead class="head">
<span>标题</span>
</thead>
<tbody class="body">
<tr class="tr-first">
<td><span>编程 coding</span></td>
<td><span>编程之美</span></td>
</tr>
<tr class="tr-second">
<td><span>Java 语言</p></td>
<td><span>Python 语言</span></td>
</tr>
<tr class="tr-third">
<td>
<p>1111</p>
</td>
</tr>
</tbody>
</table>
</div>
- 案例1:抽取 HTML 文档中
<p>
标签中所有的内容
//XPath
String result = page.getHtml().xpath("//tr[@class='tr-third']/td/p/text()").all();
//正则表达式
String result = page.getHtml().regex("<p>(.*)+</p>").all();
//CSS选择器
String result = page.getHtml().css("tr.tr-third td p","text").all();
String result = page.getHtml().$("tr.tr-third td p","text").all();
当然,这几种抽取元素的方法也可以混合使用,这个要根据抽取的页面灵活选择。
个人水平有限,如有错误,欢迎各位朋友在评论区批评指正