JSoup解析html常见问题

时间:2022-11-01 09:13:05

之前写了一个关于抓所以取某个网站用户信息的程序,大量的用到了关于JSoup解析html的知识。并且其中也遇到了一些问题,这类问题在我们以后的开发过程中可能还有机会遇到,所以今天在这里对这块做个总结。

一.Jsoup如何根据url获得对应的网页Document文档

1.常见写法  

doc=Jsoup.parse(new URL(url),4000);//参数2是连接超时设置,一旦超时则无法抓取到网页内容。以上是一种常见的写法,关于如何利用Jsoup获得Document文档,详细用法见http://www.jb51.net/article/43485.htm  

2.常见问题

(1)一般这样写获得Document文档是没有问题的,但也会遇到一些特殊情况。有些网站的网页数据必须要通过特定的post、Get请求方式才可以获取,如新华网的某个版块的首页必须要通过get方式才可以获取到数据。

doc=Jsoup.connect("http://forum.home.news.cn/list/50-133-0-1.html").timeout(3000).get();

(2)通过网页查看的源代码与通过程序返回的网页内容不一致,但这个问题是否出现取决于该网站是否设置了手机版和网页版2种代码返回方式,如何你在Document文档解析时发现,你解析语法明明没有任何错误,却依然无法得到解析出来的结果

doc=Jsoup.connect("http://forum.home.news.cn/list/50-133-0-ml")  

.timeout(3000) //设置超时时间  

.userAgent("Mozilla") //设置用户代理为MOZilla浏览器,强制使用网页版形式返回数据。

.cookie("auth","token") //设置cookie

.get(); //Get方式请求

二.如何解析DOM文档

      Jsoup将html代码段变成DOM文档模型(其实就是树模型),再通过DOM模型遍历元素匹配要寻找的数据.下面我们通过具体事例来学习如何解析DOM文档。我们将获取http://forum.home.news.cn/list/50-0-0-1.html页面中的所有帖子链接并输出打印。

    1.选择器语法:

     DOM文档模型由包含元素、属性、属性值组成。

    选择器一般语法形式为元素[属性=属性值]

    如根据以下这段html片段解析出其中的图片的src属性值
   <div class="n_logo">
      <img src="http://baidu.com/logo.png"/>
   </div>

   语法形式为:

    doc.select("div[class=n_logo]").first().select("img").first().attr("src")

其中对于含有class属性则可以简化为如下形式doc.select("div.n_logo").first().select("img").first().attr("src")

对于形如<div class="n_logo  a  b   c">这样层级的div该如何定位呢?正确的语法规则如下:

   doc.select("div.n_logo").select("a").select("div.b").select("div.c");

或者也可用doc.select(div[class=n_logo a b c])的形式(推荐使用)。

    2.下面我们讲解几个比较常用的提取有用信息的语法:

    (1)[attr^=value], [attr$=value], [attr*=value]
    这三个语法分别代表,属性以 value 开头、结尾以及包含

    (2)[attr~=regex]
   使用正则表达式进行属性值的过滤,例如 img[src~=(?i)\.(png|jpe?g)]

   以上对于提取特定元素比较有用.

选择器其他详细用法见http://www.cnblogs.com/huangjacky/archive/2011/03/08/1977721.html

    3.常见问题:

    会出现选择器语法没有问题,却无法正确解析出我们想要的数据.这个问题请参考上面常见问题(2)的解决方案。

    4.代码实战:

     详细代码如下:

import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
public class xinhua {
public static void main(String []args) throws IOException {
 parseTopicList("http://forum.home.news.cn/list/50-133-0-1.html");
 }
//一个版块单个页面的所有主题
public static ArrayList<String> parseTopicList(String url )  {
	System.out.println("***开始解析一个版块单页的所有主题***");
	ArrayList<String>topicList=new ArrayList();
		try {
		doc=Jsoup.connect(url)
				.userAgent("Mozilla")
			  .cookie("auth", "token")
			  .timeout(3000)</span>
		<span style="font-size:18px;">	  .get();
	} catch (IOException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
		int size=doc.select("div.board-list-one").size();
		String topicUrl="";
		String title="";
		String tid="";
		Pattern tPattern=Pattern.compile("detail/([0-9]*)");
		Matcher sMatcher;
		int index=0;
			for(Element ele : doc.select("dl[class=item]")){
				if(ele.select("a").size()!=0){
					topicUrl= "http://forum.home.news.cn"+ele.select("a").first().attr("href");
					sMatcher=tPattern.matcher(topicUrl);
					if (sMatcher.find()) {
						tid=sMatcher.group(1);
					}
					title = ele.select("a").first().text();
					index++;
				   topicList.add(topicUrl);
				System.out.println("this is the "+index+" "+"--->"+topicUrl);
				}
			}
			System.out.println("***解析一个版块单页的所有主题完成***");
			return topicList;
			}
}

       程序运行结果部分截图如下:

       下面我们来看一下该发展版块该页的所有主题帖子部分截图如下:

     JSoup解析html常见问题

     对比一下,我们发现.我们可以正确的抓取到我们需要抓取的数据。


三.总结

      Jsoup解析html这块知识点在编程场景下并不是经常遇到,所以没有必要深入的学习,用到3分,我们就学习5分就可以了。这点其实是很多初学者经常犯的错,总是想把某一类知识点全部弄清楚,其实完全没必要,只要你能利用文档解决问题就可以了。