使用Jsoup实现简单的页面信息爬取

使用Jsoup实现简单的页面信息爬取

首先,简单说一下个人对爬虫的理解(比较简单,以后再完善):爬虫,简单点就是从网站上来爬取你所需要的信息。从这个功能考虑的话,也就简单的分为了一下几步(本篇主要就此展开讨论):1、你需要的网址;2、你所需要的信息;3、获取信息并存储或进行相关处理。其次,简单说几个工具,最开始了解到一个httpclient的神奇东东可以实现功能强大的爬虫功能(个人理解:用java程序来封装数据包,进行网络访问,然后对访问结果进行判断,正确判断的话,再对获取到的网页信息进行解析,可以利用封装好的方法,也可以自己编写匹配过滤规则,从而获取有用的信息),后来又看到一个Jsoup的网页解析便器(比较方便的解析工具)。接下来,详细看了下 官方文档(http://www.open-open.com/jsoup/)(请认真看),又在论坛里看到了几个实例,感觉确实很方便,接下来便开始了一段Jsoup的实践之旅.

第一,Jsoup的相关操作:

1.       链接打开方式

一、 File  input = new File("D:/test.html");
	 Document  doc = Jsoup.parse(input,"UTF-8","http://baidu.com/");//第三个参数是b //aseURL,当有相对地址时,有该地址补全
二、Document  doc = Jsoup.parse("D:/test.html");//直接加载网页文件
三、Connect  conn = Jsoup.connect(url);
	Document  doc = conn.data("query","Java").//请求参数
		     					 userAgent("I'm Jsoup").//设置User-Agent
		     					 cookie("auth","token").//设置cookie
		     					 timeout(3000).//设置连接超时时间
		     					 post();//使用post方法访问URL


实例:

public class First {

	//public boolean append;
	//网页打开方法
	public Document openURL(String url){
		Document document = null;
		try {
			document = Jsoup.connect(url).timeout(40000).get();
		
			System.out.println("网页"+url+"访问成功");
		} catch (IOException e) {
			System.out.println("网页"+url+"打开失败");
		}
}

2.       解析规则

1jsoup中主要有三种操作对象:DocumentElementsElement。其中:

  • Document继承自Element类,它包含页面中的全部数据,通过Jsoup类的静态方法获得;
  • Elements是Element的集合类;
  • Element是页面元素的实体类,包含了诸多操作页面元素的方法,其中除了类似于jQuery选择器的select方法外,还有大量类似于JS和jQuery的对DOM元素进行操作的方法,如getElementById,text,addClass,等等。

2Select方法将返回一个Elements集合,并提供一组方法来抽取和处理结果。

Selector选择器概述

·        tagname:通过标签查找元素,比如:a

·        ns|tag:通过标签在命名空间查找元素,比如:可以用 fb|name 语法来查找 <fb:name> 元素

·        #id:通过ID查找元素,比如:#logo

·        .class:通过class名称查找元素,比如:.masthead

·        [attribute]:利用属性查找元素,比如:[href]

·        [^attr]:利用属性名前缀来查找元素,比如:可以用[^data-] 来查找带有HTML5 Dataset属性的元素

·        [attr=value]:利用属性值来查找元素,比如:[width=500]

·        [attr^=value][attr$=value][attr*=value]:利用匹配属性值开头、结尾或包含属性值来查找元素,比如:[href*=/path/]

·        [attr~=regex]:利用属性值匹配正则表达式来查找元素,比如: img[src~=(?i)\.(png|jpe?g)]

·        *:这个符号将匹配所有元素

Selector选择器组合使用

·        el#id:元素+ID,比如: div#logo

·        el.class:元素+class,比如: div.masthead

·        el[attr]:元素+class,比如: a[href]

·        任意组合,比如:a[href].highlight

·        ancestorchild:查找某个元素下子元素,比如:可以用.body p 查找在"body"元素下的所有 p元素

·        parent> child:查找某个父元素下的直接子元素,比如:可以用div.content > p 查找 p 元素,也可以用body > * 查找body标签下所有直接子元素

·        siblingA+ siblingB:查找在A元素之前第一个同级元素B,比如:div.head + div

·        siblingA~ siblingX:查找A元素之前的同级X元素,比如:h1 ~ p

·        el,el, el:多个选择器组合,查找匹配任一选择器的唯一元素,例如:div.masthead, div.logo

伪选择器selectors

·        :lt(n):查找哪些元素的同级索引值(它的位置在DOM树中是相对于它的父节点)小于n,比如:td:lt(3) 表示小于三列的元素

·        :gt(n):查找哪些元素的同级索引值大于n,比如 div p:gt(2)表示哪些div中有包含2个以上的p元素

·        :eq(n):查找哪些元素的同级索引值与n相等,比如:form input:eq(1)表示包含一个input标签的Form元素

·        :has(seletor):查找匹配选择器包含元素的元素,比如:div:has(p)表示哪些div包含了p元素

·        :not(selector):查找与选择器不匹配的元素,比如: div:not(.logo) 表示不包含 class=logo 元素的所有 div列表

·        :contains(text):查找包含给定文本的元素,搜索不区分大不写,比如: p:contains(jsoup)

·        :containsOwn(text):查找直接包含给定文本的元素

·        :matches(regex):查找哪些元素的文本匹配指定的正则表达式,比如:div:matches((?i)login)

·        :matchesOwn(regex):查找自身包含文本匹配指定正则表达式的元素

·        注意:上述伪选择器索引是从0开始的,也就是说第一个元素索引值为0,第二个元素index1

可以查看Selector API参考来了解更详细的内容

 

第二,Jsoup实例

1.       爬取一个源URL(http://apk.hiapk.com/)下的链接(安卓游戏),并获取新链接(安卓游戏)的内容

import java.io.IOException;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.select.Elements;

public class TestJsoup {
    
    public  Document getDocument (String url){
        try {
            return Jsoup.connect(url).get();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static void main(String[] args) {
        TestJsoup t = new TestJsoup();
        Document doc= t.getDocument("http://apk.hiapk.com/");
        //Document doc = t.getDocument("http://www.weather.com.cn/html/weather/101280101.shtml");
        //Document doc = t.getDocument("http://www.cnblogs.com/xiaoMzjm/p/3899366.html");//zijichangshi
        // 获取目标HTML代码
        
        //找到游戏链接,并跳转到游戏界面
        Elements elements1 = doc.select("a[title = 安卓游戏]");
        String href = elements1.attr("href");//获得链接
        System.out.println(href);//控制台查看
        Document docgame = t.getDocument(href);//打开获取的新链接
        System.out.println(docgame.select("title").text());
               
        Elements elements2 = docgame.select("a[class = s2]");
        String href2 = elements2.attr("href");
        String txt = elements2.text();
        System.out.println(href2);
        Document docgame2 = t.getDocument(href2);
        System.out.println(docgame2.select("title").text());        
    }
}

 2 .      获取源URL下所有游戏的链接及其相关游戏详细信息

步骤:

1)源URL

2)游戏页面

3) 游戏分类页面

4) 单个游戏的链接

5) 单个游戏的详细信息


1)  源URL :  http://apk.hiapk.com/

2)  游戏页:

//获取  游戏  链接
		Elements gameLink = doc.select("a[title = 游戏-安卓市场]");
		String url2 = gameLink.attr("abs:href");
		Document doc2 = first.openURL(url2);

3)  游戏分类页

//获取    游戏分类    链接
		Elements gameLink2 = doc2.select("div.cate_list_box");
		
		Elements gameLinkType = gameLink2.select("a");
		int length = gameLinkType.size();

4)  单个游戏的链接:可能遇到多页的情况,这时候要进行分页处理

简单思路:获取所有分页的URL , 求并集便是一类游戏下的所有游戏

//获取游戏分类下的游戏列表
	public void GameTypeFetch(String url, String table){

		First gtfetch = new First();
		Document doc = gtfetch.openURL(url);
		Elements gameLink = doc.select("ul#appSoftListBox").select("li");
		int length = gameLink.size();
		
		
		String urlGame[] = new String[length];
		String nameGame[] = new String[length];
		int temp = 0;
		/*for(int i=0; i<length; i++){
			urlGame[i] = gameLink.get(2*i+1).attr("abs:href");
			nameGame[i] = gameLink.get(2*i+1).text();
			System.out.println(i+"  :  "+urlGame[i]+"  :  "+nameGame[i]);
		}*/
		System.out.println("    "+length);
		for(Element e : gameLink){//单个游戏的链接
			urlGame[temp] = e.select("a").get(1).attr("abs:href");
			nameGame[temp] = e.select("a").get(1).text();
			System.out.println("    "+temp+"  :  "+urlGame[temp]+"  :  "+nameGame[temp]);
			gtfetch.gameItems(nameGame[temp],urlGame[temp],false,0,table);						
			temp++;			
		}
								
	}

   5)单个游戏的详细信息

              注意对其它版本的处理

//获取游戏的具体详细信息
	public void gameItems(String gameName, String gameLink, boolean otherVersion, int version, String table){
		
		//int tableindex = 0;
		//变量声明,存储游戏相关信息
		String name = gameName;
		String link = gameLink;
		//属性1
		int starsize = 5;
		String star[] =new String[starsize];
		String starNUM = null;
		int numEVAL = 0;//有多少人评分
		//属性2
		String des = null;
		String updes = null;
		//属性3
		String author = null;
		String down = null;
		String size = null;
		String type = null;
		String language = null;
		String time = null;
		//String name = null;
		//属性4
		int VSNUM = 0;
		String otherVS[];
		
		
		//获取当前游戏信息
		Elements details;
		First gtfetch = new First();
		Document doc = gtfetch.openURL(link);
		boolean valid = gtfetch.isValid();
		if(valid==true){
			//System.out.println(eee);
			//获取属性3
			details = doc.select("div.line_content");
		if(!details.isEmpty()){
			
			System.out.println(details.size());
			author = details.get(0).select("span").get(1).text();
			down = details.get(1).select("span").get(1).text();
			size = details.get(2).select("span").get(1).text();
			type = details.get(3).select("span").get(1).text();
			language = details.get(4).select("span").get(1).text();
			time = details.get(7).select("span").get(1).text();
			
			//获取属性2
			des = doc.select("pre#softIntroduce").text();
			updes = doc.select("pre.soft_imprint_font").text();
			//获取属性1
			Elements eval = doc.select("div.star_line");
			
			for(Element e : eval){
				star[--starsize] = e.text();
			}
			
			starNUM = doc.select("div.star_num").text();
			numEVAL = Integer.parseInt(doc.select("span#startCount").text());//有多少人评分
			
			if(!otherVersion){
				//typelength++;
				//tableindex = typelength;
				//获取属性4
				Elements otherversions = doc.select("div#otherSoftBox");
				Elements versions = otherversions.select("dl.soft_item_dl");
				
				int versionlength = versions.size();
				VSNUM = versionlength + 1;
				//otherVS = new String[otherVSNUM];
				//System.out.println(otherVSNUM);
				
				for(int ind=(versions.size()-1);ind>=0;ind--){
					String otherurl = versions.get(ind).select("a[href]").first().attr("abs:href");
					gameItems(name,otherurl,true,(versions.size()-ind+1),table);
					
				}
	
			}else{
				typelength++;
				System.out.println(name+"    没有其他版本!");
				VSNUM = version;
				tableindex = typelength;			
			}
					
			System.out.println(name+"  "+link+"  "+author+"  "+down+"  "+size+"  "+type+"  "+"  "+time+"  "+starNUM+"  "+numEVAL+"  "+VSNUM);
					
		}
		}
				
	}

综上,使用Jsoup也可以实现简单的爬虫程序,但更适合于网页的解析,爬虫程序,一般都有一个基本的框架,通过一系列的种子URL,获取所需链接(往往数量较多),这时,便遇到了爬取到的大量链接的访问问题,一般,将链接分为两大部分,以访问的链接和带访问的链接(用队列或者堆栈存储,方便操作),有时,会将采集到的信息用数据库进行存储,以方便对采集的信息进行进一步的处理(实现了一个简单的mysql数据库的实例)。该文主要是以一个简单实例来介绍Jsoup的使用,从而对Jsoup有一个更深刻的认识,同时,对爬虫也有一个初步的了解,针对于爬虫的复杂程度,所采用的爬虫结构也会有所变化!

望对刚刚入门的你,会有所帮助!





  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值