整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

java 如何解析网页?

送HTTP请求:首先,你需要向目标网页发送HTTP请求以获取其HTML内容。这可以通过Java的内置库java.net.HttpURLConnection或者使用更高级的库如Apache HttpClient、OkHttp等来完成。

读取响应内容:一旦你发送了请求并收到了响应,你需要读取响应的内容,这通常是HTML格式的字符串。

解析HTML:然后,你需要解析HTML字符串以提取所需的信息。这可以通过正则表达式来完成,但通常建议使用专门的HTML解析库,如Jsoup。Jsoup提供了一种非常方便的方式来解析HTML文档,并可以通过类似于CSS或jQuery的选择器语法来提取和操作数据。

如果你需要处理更复杂的网页或进行更高级的网页抓取和解析任务,你可能还需要考虑使用如Selenium这样的浏览器自动化工具来模拟真实的浏览器行为。但是,请注意,频繁或大规模地抓取网页可能会违反网站的使用条款,甚至可能构成法律问题。

时候编辑器传到后台的内容是带Html标签的,或者有时候需要形成一个完整的Html文档,也或者需要解析其中的文字(text()),Java后台处理用Jsoup非常方便,也可以用选择器快速获取元素,类似于jQuery。获取到文档对此之后对其处理与JS处理DOM一样方便,选取元素也类似于JS,也有类似于jQuery的语法,官方的解释

1.最基本的解析Html字符串

 @Test
 public void testHtmlToString2() {
 String html = "<p>这是一个段落<img src=\"test.img\"/>内容;</p>";
 Document doc = Jsoup.parse(html);
 System.out.println(doc); // 输出带标签的html文档
 System.out.println("---------------------\n"+doc.text()); // 输出内容
 Elements element = doc.getElementsByTag("p");
 System.out.println("---------------------\n"+element.get(0).html());
 }

结果:

<html>
 <head></head>
 <body>
 <p>这是一个段落<img src="test.img">内容;</p>
 </body>
</html>
---------------------
这是一个段落内容;
---------------------
这是一个段落<img src="test.img">内容;

2.解析字符串

 // 解析html字符串
 @Test
 public void testHtmlToString() {
 String html = "<html><head><title>First parse</title></head>"
 + "<body><p style='center'>Parsed HTML into a doc.</p></body></html>";
 Document doc = Jsoup.parse(html);
 System.out.println(doc); // 输出带标签的html文档
 System.out.println("---------------------\n"+doc.text()); // 输出内容
 }

结果:

<html>

<head>

<title>First parse</title>

</head>

<body>

<p style="center">Parsed HTML into a doc.</p>

</body>

</html>

---------------------

First parse Parsed HTML into a doc.

3.// 解析body片段

 @Test
 public void test2() {
 String html = "<div><p>Lorem ipsum.</p>";
 Document doc = Jsoup.parseBodyFragment(html);
 System.out.println(doc);
 System.out.println(doc.text());
 }

结果:

<html>

<head></head>

<body>

<div>

<p>Lorem ipsum.</p>

</div>

</body>

</html>

Lorem ipsum.

4.// 解析一个url与用选择器选择元素(相当于查看源码)

 @Test
 public void test4() throws IOException {
 Document doc = Jsoup.connect("http://qiaoliqiang.cn:8080/").get();
 String title = doc.title();// 获取title
 System.out.println(title);
 System.out.println("---------------------\n"+doc.toString()+"---------------------\n");// 输出文档全部
 Elements links = doc.getElementsByTag("a");
 for (Element ele : links) {
 System.out.println(ele.toString());
 }
 }

Apache Tomcat/7.0.72

---------------------

<!doctype html>

<html lang="en">

<head>

<title>Apache Tomcat/7.0.72</title>

<link href="favicon.ico" rel="icon" type="image/x-icon">

<link href="favicon.ico" rel="shortcut icon" type="image/x-icon">

..........

5.选择器解析HTML并且提取input的value值:(获取元素的属性)

 /**
 * <span class="bigNum">二</span>、
 * <span><input class="el_modifiedTitle" value="多选题" type="text"> </span>
 * <span>(每到题 <input class="el_modifiedGrade" value="2" type="text"> </span>
 * <span> 分;共</span><span class="numTotal">4分/</span>
 * <span class="numQues">2题)</span>
 * 
 * @param html
 * @return
 */
 // 去掉大题的标签
 public static String removeBigQues(String html) {
 StringBuffer sb = new StringBuffer();
 Document doc = Jsoup.parse(html);
 System.out.println(doc);
 System.out.println(doc.text());
 sb.append(doc.select(".bigNum").get(0).text() + ". ");
 sb.append(doc.select(".el_modifiedTitle").get(0).attr("value"));
 sb.append(doc.select("span").get(2).text() + doc.select(".el_modifiedGrade").get(0).attr("value"));
 sb.append(doc.select("span").get(3).text());
 sb.append(doc.select("span").get(4).text());
 sb.append(doc.select("span").get(5).text());
 System.out.println(sb.toString());
 return sb.toString();
 }

补充:今天发现Jsoup竟然没有解析元素style的方法,所以只能自己手写

先获取到style属性,再对style属性进行处理,例如:

 String style = "position: absolute; width: 500px; height: 552px;";
 String extract = "width";
 if (style.contains(extract)) {
 style = style.substring(style.indexOf(extract));
 System.out.println(style);
 style = style.substring(0, style.indexOf(";"));
 System.out.println(style);
 String attr = style.substring(style.indexOf(":") + 2);
 System.out.println(attr.substring(0, attr.indexOf("px")));
 }

补充:元素的html()与outerHtml()的区别

html()会返回包括子元素的内容以及标签,不包括自己

outerHtml()会返回包括自己在内的元素。

在jQuery中如果返回子元素的内容也是html(),如果返回包括自己的内容需要用$("#chartdiv").prop("outerHTML");//会返回包括自己在内的内容

ava中解析HTML框架之Jsoup

场景是这样的,本来是想申请一个第三方支付接口判断用户支付是否成功,后来发现不需要申请接口也可以通过订单号查询页面获取支付结果,这样就可以直接解析html来判断支付结果了,这就引入了本文的主题,Jsoup解析html

当然jsoup不只有上面的应用场景,它还有一个应用场景,就是爬虫!

题外话:上面场景中,使用支付接口其实才是最稳当的办法,但是支付接口申请周期长,而且一些情况下并不是免费的,再者一些支付接口只支持一种语言,可能和本项目不是一个语言(比如项目是Java的,但是人家提供的支付接口只支持PHP),这样增加了系统复杂度,如果业务量大且要求准确的场景下应当使用支付接口,否则可以取巧解析html,解析html有一个不好的地方就是如果html结构变化了,那么接口就得重写,都有优缺点,看场景选择。

Jsoup简介与使用

官网:https://jsoup.org/

jsoup 提供了简便的API,使用了HTML5 DOM方法和CSS选择器用来解析HTML。其实现了WHATWG HTML5 规范,像浏览器一样解析HTML。

  • 从文件,URL,字符串抓取和解析HTML
  • 使用DOM遍历或者CSS选择器来查找和提取数据
  • 操作HTML元素,属性和文字
  • 清除用户提交的安全白名单以外的内容,以防止XSS攻击
  • 美化HTML

引入依赖

<dependency>
    <groupId>org.jsoup</groupId>
    <artifactId>jsoup</artifactId>
    <version>1.11.2</version>
</dependency>

解析HTML

  1. 从字符串解析
String html = "<html><head><title>First parse</title></head>"
  + "<body><p>Parsed HTML into a doc.</p></body></html>";
Document doc = Jsoup.parse(html);
  1. 从URL解析
// 简洁版
Document doc = Jsoup.connect("http://example.com/").get();
String title = doc.title();

//完整版
doc = Jsoup.connect("http://example.com")
  .data("query", "Java")
  .userAgent("Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36")
  .cookie("auth", "token")
  .timeout(3000)
  .post();
  1. 从文件解析
File input = new File("/tmp/input.html");
Document doc = Jsoup.parse(input, "UTF-8", "http://example.com/");

提取HTML

  • 遍历HTML
File input = new File("/tmp/input.html");
Document doc = Jsoup.parse(input, "UTF-8", "http://example.com/");

Element content = doc.getElementById("content");
Elements links = content.getElementsByTag("a");
for (Element link : links) {
  String linkHref = link.attr("href");
  String linkText = link.text();
}
  • 提取数据
String html = "<p>An <a href='http://example.com/'><b>example</b></a> link.</p>";
Document doc = Jsoup.parse(html);
Element link = doc.select("a").first();

String text = doc.body().text(); // "An example link"
String linkHref = link.attr("href"); // "http://example.com/"
String linkText = link.text(); // "example""

String linkOuterH = link.outerHtml(); 
    // "<a href="http://example.com"><b>example</b></a>"
String linkInnerH = link.html(); // "<b>example</b>"
  • 相对路径转换成绝对路径,一些a标签使用的是相对路径,下面的代码可以将其转换成绝对路径
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/"

CSS选择器

Jsoup支持CSS选择器,用的是 Element.select(String selector)方法

File input = new File("/tmp/input.html");
Document doc = Jsoup.parse(input, "UTF-8", "http://example.com/");

Elements links = doc.select("a[href]"); // a with href
Elements pngs = doc.select("img[src$=.png]");
  // img with src ending .png

Element masthead = doc.select("div.masthead").first();
  // div with class=masthead

Elements resultLinks = doc.select("h3.r > a"); // direct a after h3

如何快速定位页面上元素的内容?答案是打开Chrome,按F12打开开发者工具,定位到想要的DOM节点,右键,copy,选择Copy selector,即可生成CSS选择器,类似于body > div > div.content > div.col2 > div > h3:nth-child(10)

遗憾的是Jsoup不支持Xpath选择器,但是早就有人意识到这个问题了,所以诞生了JsoupXpath

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

项目地址:https://github.com/zhegexiaohuozi/JsoupXpath

感兴趣的可以看一下测试用例:里面包含了大量的使用场景:https://github.com/zhegexiaohuozi/JsoupXpath/blob/master/src/test/java/org/seimicrawler/xpath/JXDocumentTest.java

操作HTML

jsoup可以在插入、删除、提取HTML,直接看例子代码

  • 设置属性
//设置属性
doc.select("div.comments a").attr("rel", "nofollow");
doc.select("div.masthead").attr("title", "jsoup").addClass("round-box");
  • 插入html
//插入html
Element div = doc.select("div").first(); // <div></div>
div.html("<p>lorem ipsum</p>"); // <div><p>lorem ipsum</p></div>
div.prepend("<p>First</p>");
div.append("<p>Last</p>");
// now: <div><p>First</p><p>lorem ipsum</p><p>Last</p></div>

Element span = doc.select("span").first(); // <span>One</span>
span.wrap("<li><a href='http://example.com/'></a></li>");
// now: <li><a href="http://example.com"><span>One</span></a></li>
  • 设置文本
//设置文本
Element div = doc.select("div").first(); // <div></div>
div.text("five > four"); // <div>five > four</div>
div.prepend("First ");
div.append(" Last");
// now: <div>First five > four Last</div>

避免XSS攻击( cross-site scripting )

String unsafe = 
  "<p><a href='http://example.com/' onclick='stealCookies()'>Link</a></p>";
String safe = Jsoup.clean(unsafe, Whitelist.basic());
// now: <p><a href="http://example.com/" rel="nofollow">Link</a></p>

参考

  • https://jsoup.org/
  • http://www.wanghaomiao.cn/archives/25/
  • https://github.com/zhegexiaohuozi/JsoupXpath