在抓取网络上的资源时,我们经常会和网页打交道,很多时候我们都需要网页上的资源进行抓取,这个时候Jsoup就能帮助我们快速解析Html页面的结构,并分离出我们想要的资源。
解析一个Html字符串
String html = "<html><head><title>First parse</title></head>"
+ "<body><p>Parsed HTML into a doc.</p></body></html>";
Document doc = Jsoup.parse(html);
通过Jsoup.parse方法将目标字符串解析成一个文档,该文档将页面中的各种元素都组织成对应的文档节点,具体的对象模型如下:
- 文档由多个Elements和TextNodes组成
- 其继承结构如下:Document继承Element继承Node. TextNode继承 Node.
- 一个Element包含一个子节点集合,并拥有一个父Element。他们还提供了一个唯一的子元素过滤列表。
使用选择器语法来查找元素
Jsoup可以让我们使用类似于CSS或jQuery的语法来查找和操作元素,这种方法查找起来十分方便快捷。
Elements links = doc.select("a[href]"); //带有href属性的a元素
Elements pngs = doc.select("img[src$=.png]");
//扩展名为.png的图片
Element masthead = doc.select("div.masthead").first();
//class等于masthead的div标签
Elements resultLinks = doc.select("h3.r > a"); //在h3元素之后的a元素
这个select 方法在Document, Element,或Elements对象中都可以使用。且是上下文相关的,因此可实现指定元素的过滤,或者链式选择访问。Select方法将返回一个Elements集合,并提供一组方法来抽取和处理结果。
Selector选择器常见语法
- tagname: 通过标签查找元素,比如:a
- *: 这个符号将匹配所有元素
- #id: 通过ID查找元素,比如:#logo
- .class: 通过class名称查找元素,比如:.masthead
- [attribute]: 利用属性查找元素,比如:[href]
- [attr=value]: 利用属性值来查找元素,比如:[width=500]
- [^attr]: 利用属性名前缀来查找元素,比如:可以用[^data-] 来查找带有HTML5 Dataset属性的元素
- [attr^=value], [attr$=value], [attr*=value]: 利用匹配属性值开头、结尾或包含属性值来查找元素,比如:[href*=/path/]
- [attr~=regex]: 利用属性值匹配正则表达式来查找元素,比如: img[src~=(?i).(png|jpe?g)]
语法组合使用
- el#id: 元素+ID,比如: div#logo
- el.class: 元素+class,比如: div.masthead
- el[attr]: 元素+class,比如: a[href]
- 任意组合,比如:a[href].highlight
- ancestor child: 查找某个元素下子元素,比如:可以用.body p 查找在”body”元素下的所有 p元素
- el, el, el:多个选择器组合,查找匹配任一选择器的唯一元素,例如:div.masthead, div.logo
- siblingA + siblingB: 查找在A元素之前第一个同级元素B,比如:div.head + div
- siblingA ~ siblingX: 查找A元素之前的同级X元素,比如:h1 ~ p
通过这些灵活的选择器,我们可以快速定位我们想要的资源,并且对其进行抽取或修改。
从一组Element里抽取资源
如果网页上有一组同类资源排列在一起,通过上面的语法我们一般会得到一个同类型的资源集合,通过遍历这个集合我们就能对各个资源逐一访问。例如:网页的《p》元素中,包含很多链接《a》,如下图所示:
则需要通过迭代器形式对每个《a》进行访问.
Elements p = doc.select("p.kw_main");
Iterator<Element> keywords = p.select("a").iterator();
String keywordString = "";
while(keywords.hasNext()){
keywordString += keywords.next().text() + ";";
}