一、定义
jsoup官网,jsoup是一个用于处理HTML的Java库,它提供了一个非常方便类似于使用DOM,CSS和jQuery的方法的API来提取和操作数据。
jsoup实现WHATWG HTML5规范,并将HTML解析为与现代浏览器相同的DOM。
- 从URL,文件或字符串中提取并解析HTML
- 查找和提取数据,使用DOM遍历或CSS选择器
- 操纵HTML元素,属性和文本
- 根据安全的白名单清理用户提交的内容,以防止XSS攻击
- 输出整洁的HTML
jsoup旨在处理发现所有格式有差异的HTML,从原始和验证,到无效的标签,jsoup将创建一个明智的解析树。
二、主要作用
- DOM:将HTML解析为与现代浏览器相同的DOM,和js中的document对象一样,用getElementById等方法获取元素
- CSS:利用CSS选择器选择src等属性
三、开源
jsoup是一个根据自由MIT许可证分发的开源项目,源代码可在GitHub获得:http://github.com/jhy/jsoup/
四、jsoup安装
要运行任何jsoup示例,需要先安装好jsoup相关Jar包,安装jsoup主要有三种方法:
- 通过Maven的pom.xml配置文件
- 使用jsoup.jar文件
- Gradle的配置文件
通过Maven的pom.xml文件配置:
org.jsoup
jsoup
1.15.3
jsoup是完全自包含的,没有依赖关系。
五、jsoup应用的主要类
然完整的类库中有很多类,但大多数情况下,下面给出3个类是我们需要重点了解的。
5.1 org.jsoup.Jsoup
类
jsoup类是任何Jsoup程序的入口点,并将提供从各种来源(URL、文件、字符串)加载和解析HTML文档的方法。
5.1.1 从URL加载解析HTML文档
方式一:
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import java.io.IOException;
import java.net.URL;
public class Test {
public static void main(String[] args) throws IOException {
Document document = Jsoup.parse(new URL("http://www.yiibai.com"), 30000);
String title = document.title();
//易百教程™ - 专注于IT教程和实例
System.out.println(title);
}
}
方式二:
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import java.io.IOException;
public class Test {
public static void main(String[] args) throws IOException {
Document document = Jsoup.connect("http://www.yiibai.com").get();
String title = document.title();
//易百教程™ - 专注于IT教程和实例
System.out.println(title);
}
}
5.1.2 从文件加载解析HTML文档
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import java.io.File;
import java.io.IOException;
public class Test {
public static void main(String[] args) throws IOException {
Document document = Jsoup.parse( new File( "D:/yibai.html" ) , "utf-8" );
String title = document.title();
//易百教程™ - 专注于IT教程和实例
System.out.println(title);
}
}
备注:在浏览器中打开http://www.yiibai.com
网站,然后ctrl+s将该网站保存到本地yibai.html。
5.1.3 从字符串加载解析HTML文档
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import java.io.IOException;
public class Test {
public static void main(String[] args) throws IOException {
String html = "易百教程™ - 专注于IT教程和实例 "
+ "Parsed HTML into a doc.
";
Document document = Jsoup.parse(html);
String title = document.title();
//易百教程™ - 专注于IT教程和实例
System.out.println(title);
}
}
5.2 org.jsoup.nodes.Document
类
该类表示通过jsoup库加载HTML文档。可以使用此类执行适用于整个HTML文档的操作。Element类的重要方法可以参见 http://jsoup.org/apidocs/org/jsoup/nodes/Document.html
5.2.1 DOM
document对象和JavaScript里的document是一个东西,js里能用的方法这里都能调用。
Element element = document.getElementById("J_goodsList");
5.2.2 CSS选择器
下面例子中从HTML提取带a[href] 、src、 link[href]属性的元素,再用这些元素的attr函数提取更精确额内容。
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 Test {
public static void main(String[] args) throws IOException {
Document doc = Jsoup.connect("http://www.yiibai.com").get();
Elements links = doc.select("a[href]");
Elements media = doc.select("[src]");
Elements imports = doc.select("link[href]");
System.out.println("links size:=" + links.size());
for (Element link : links) {
System.out.println(link.attr("abs:href"));
}
System.out.println("media size:=" + media.size());
for (Element src : media) {
if (src.tagName().equals("img")) {
System.out.println(src.tagName() + " " + src.attr("abs:src") + " " + src.attr("width"));
} else {
System.out.println(src.tagName() + " " + src.attr("abs:src") + " " + src.attr("width"));
}
}
System.out.println("imports size:=" + imports.size());
for (Element link : imports) {
System.out.println(link.tagName() + " " + link.attr("abs:href") + " " + link.attr("rel"));
}
}
}
5.3 org.jsoup.nodes.Element
类
HTML元素是由标签名称,属性和子节点组成。 使用Element类,您可以提取数据,遍历节点和操作HTML。Element类的重要方法可参见 http://jsoup.org/apidocs/org/jsoup/nodes/Element.html
六、常用功能
6.1 获取URL的链接
Elements类中可以使用for-each循环遍历元素。Element类提供了attr()和text()方法来返回链接的链接和对应的文本。
Document doc = Jsoup.connect("http://www.yiibai.com").get();
Elements links = doc.select("a[href]");
for (Element link : links) {
System.out.println("\nlink : " + link.attr("href"));
System.out.println("text : " + link.text());
}
6.2 获取URL的元信息
Document doc = Jsoup.connect("http://www.yiibai.com").get();
String keywords = doc.select("meta[name=keywords]").first().attr("content");
System.out.println("Meta keyword : " + keywords);
String description = doc.select("meta[name=description]").get(0).attr("content");
System.out.println("Meta description : " + description);
6.3 获取URL的图片
Document doc = Jsoup.connect("http://www.yiibai.com").get();
Elements images = doc.select("img[src~=.+(.JPEG|.jpeg|.JPG|.jpg|.PNG|.png|.GIF|.gif)$");
for (Element image : images) {
System.out.println("src : " + image.attr("src"));
System.out.println("height : " + image.attr("height"));
System.out.println("width : " + image.attr("width"));
System.out.println("alt : " + image.attr("alt"));
}
6.4 获取表单参数
Document doc = Jsoup.parse(new File("D:/yibai.html"),"utf-8");
Element loginform = doc.getElementById("registerform");
Elements inputElements = loginform.getElementsByTag("input");
for (Element inputElement : inputElements) {
String key = inputElement.attr("name");
String value = inputElement.attr("value");
System.out.println("Param name: "+key+" \nParam value: "+value);
}
七、jsoup上传图片到OSS
7.1 OssComponent
@Slf4j
@Component
public class OssComponent {
@Resource
private OssConfig ossConfig;
@Value("${spring.profiles.active}")
private String active;
public String uploadByInputStream(InputStream inputStream,
Long memberId, String fileName) {
String bucketName = getBucketName();
// /content/{memberId}/{datetime.now.date}/xxxxxxx.jpg
String date = DateFormatUtils.format(new Date(), "yyyy-MM-dd");
String objectName = StrUtil.format("content/{}/{}/{}", memberId, date, fileName);
OSS ossClient = new OSSClientBuilder().build(ossConfig.getEndpoint(), ossConfig.getAccessKeyId(), ossConfig.getAccessKeySecret());
try {
PutObjectResult result = ossClient.putObject(bucketName, objectName, inputStream);
if (StringUtil.isNotEmpty(result.getETag())) {
String newUrl = StrUtil.format("https://{}.{}/{}",bucketName,ossConfig.getEndpoint(),objectName);
return newUrl;
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (ossClient != null) {
ossClient.shutdown();
}
}
return null;
}
private String getBucketName() {
if ("prod".equals(active)) {
return "prod-public";
} else {
return "test-public";
}
}
}
7.2 OssConfig
@Data
@Component
@ConfigurationProperties(prefix="aliyun-oss")
public class OssConfig {
private String endpoint;
private String accessKeyId;
private String accessKeySecret;
private String roleArn;
private Long durationSeconds;
private String bucketName;
}
7.3 loadImage
/**
* 上传图片到OSS
*
* @param originUrl:可访问的待上传图片的全地址
* @param memberId
* @return 上传到OSS的新地址
*/
public String loadImage(String originUrl, Long memberId) {
try {
String[] fileNameArray = originUrl.split("/");
String fileName = fileNameArray[fileNameArray.length - 1];
if (fileName.contains("?")) {
fileName = fileName.split("\\?")[0];
}
byte[] byteArray = Jsoup.connect(originUrl).validateTLSCertificates(false).ignoreContentType(true).maxBodySize(Integer.MAX_VALUE).execute().bodyAsBytes();
InputStream inputStream = new ByteArrayInputStream(byteArray);
return ossComponent.uploadByInputStream(inputStream, memberId, fileName);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}