先看一个简单的例子,新建一个Maven项目:
在项目的pom.xml文件中添加如下依赖:
<dependency>
<groupId>org.jsoupgroupId>
<artifactId>jsoupartifactId>
<version>1.13.1version>
dependency>
确认项目下的External Libraries中包含如下jar包
我们的例子是提取到百度首页的标题,如下图所示:
使用jsoup库可以很容易做到这事儿,
package com.andy;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import java.io.IOException;
public class JsoupDemo {
public static void main(String[] args) throws IOException {
Document document = Jsoup.connect("http://www.baidu.com").get();
System.out.println(document.title());
}
}
结果如下:
通过Jsoup.connect("http://www.baidu.com").get()
我们获取到了百度首页的HTML文档并返回一个Document
对象(它就代表了HTML文档),使用Document
对象的title()
方法获取到了HTML文档的标题。
有多个方法获取到Document
对象。
该方法从字符串解析出一个Document
对象,
Document document = Jsoup.parse("");
System.out.println(document);
可以看到对于缺失的标签,jsoup库帮我们补全。
该方法从字符串解析出一个Document
对象,与Jsoup.parse(String html)
方法不同的是,此方法会将html
插入到body
标签中,
Document document = Jsoup.parseBodyFragment("");
System.out.println(document);
该方法从目标URL解析出一个Document
对象,正如样例所示。
###Jsoup.parse(File in, String charset, String baseUri)
该方法从文件中解析出一个Document
对象,我们将百度首页的html文档保存到本地,然后用此方法得到一个Document
对象:
File file = new File("./index.html");
Document document = Jsoup.parse(file, "UTF-8");
System.out.println(document);
获取到了Document
对象有什么用呢?我们可以通过它的很方便的方法提取数据。
在Document
对象上我们可以使用一些类DOM方法,比如:
getElementById(String id)
getElementsByTag(String tag)
getElementsByClass(String className)
getElementsByAttribute(String key)
还是用百度首页来举例:
File file = new File("./index.html");
Document document = Jsoup.parse(file, "UTF-8");
Elements elements = document.getElementsByTag("a");
for (Element element : elements) {
System.out.println(element);
}
我们getElementsByTag()
方法获取到了整个页面的a
元素,然后打印输出每个元素。
可以用下列方法提取元素的数据:
attr(String key)
获取元素key
属性的值attributes()
获取元素所有属性id()
获取元素id属性的值className
和classNames
获取元素class属性的值text()
获取元素内容例如:
File file = new File("./index.html");
Document document = Jsoup.parse(file, "UTF-8");
Elements elements = document.getElementsByTag("a");
for (Element element : elements) {
System.out.println(element.text() + " : " + element.attr("href"));
}
除了类DOM方法外,还可以使用CSS选择器语法对元素进行筛选,主要是用Element.select(String selector)
方法。
File file = new File("./index.html");
Document document = Jsoup.parse(file, "UTF-8");
Elements elements = document.select("a[href]");
for (Element element : elements) {
System.out.println(element.text() + " : " + element.attr("href"));
}
如上例所示,通过select()
方法找到了所有带有href
属性的a
标签。值得注意的是,select()
方法可以在Document
,Element
或Elements
对象上使用。
更多选择器语法请看Use selector-syntax to find elements。
有时我们需要将资源的相对路径转换为绝对路径,我们可以用如下两种方法:
Document doc = Jsoup.connect("http://jsoup.org").get();
Element link = doc.select("a").first();
String relHref = link.attr("href"); // == "/"
String absHref = link.attr("abs:href"); // "http://jsoup.org/"
// 等价于
String absLink = link.absUrl("href") // "http://jsoup.org/"
了解了上述内容后,我们现在可以尝试爬取豆瓣电影TOP250啦!
观察其URLhttps://movie.douban.com/top250?start=0&filter=
,可以发现页数和URL是一一对应的,start
的值会等于当前页i
减1乘以25,即start=(i-1)*25
,因此通过改变start
的值就可以请求到不同的HTML页面。我们对页面上的每部电影信息做进一步分析:
可以看到每部电影都包含在一个class名为item
的div
标签中,作为示例我们这里只提取每部电影的标题和URL。完整代码如下所示:
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import java.io.IOException;
public class JsoupDemo {
public static void main(String[] args){
String baseUrl = "https://movie.douban.com/top250?start=%d&filter=";
for (int i = 0; i < 10; i++) {
String url = String.format(baseUrl, i * 25);
try {
parsePage(url);
} catch (Exception e) {
System.out.println("Error !!");
}
}
}
public static void parsePage(String src) throws IOException {
Document document = Jsoup.connect(src).get();
Elements elements = document.select("div.item");
for (Element element : elements) {
String title = element.select("span.title").first().text();
String url = element.select("div.hd > a").first().attr("href");
System.out.println("title : " + title + " url : " + url);
}
}
}
抓取结果如下: