java版爬虫htmlparser的使用

1、我写的这个爬虫是根据新浪微博的网址去爬它的文章的。

2、根据页面的标签来爬。

3、新浪的热门文章有一道防爬虫的机制,其实也简单,就是请求头的问题,写了就能绕过登陆模块直接进行爬数据了。

4、这只是一个小demo,效果通了的话再看看原理吧。

那先放一份完整的方法体吧

public Map<String, String> sinacrawlervoid(String url) throws Exception{
		// TODO Auto-generated constructor stub
				// 输入网址 url
				String content = null;  //用于存储返回的html代码
				Parser parser = new Parser();  //用于转存为htmlparser可操作的格式
				//使用httpclient,主要用来使用请求头发送数据,接收相应返回的数据
				HttpClient client = new HttpClient();
				System.out.println(url);
				// 设置请求头,绕过新浪防爬虫机制
				HttpMethod method = new GetMethod(url);
				try {
					method.addRequestHeader("Accept",
							"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8");
					method.addRequestHeader("Accept-Language", "zh-CN,zh;q=0.8");
					method.addRequestHeader("Cache-Control", "no-cache");
					method.addRequestHeader("Connection", "keep-alive");
					method.addRequestHeader("Pragma", "no-cache");
					method.addRequestHeader("Content-Type", "text/html; charset=UTF-8");
					method.addRequestHeader("Cookie",
							"SCF=AuD5cb41vDeFJn-dHO9IrNlcTxq50vNxCCYhPUNxdhtrbUJEQJfxBkljP-8wVrATBTvovTuTFzt4y-mBLm4CYwk.; SUB=_2AkMvByHQdcNhrAJZnPsVzW3gZYlH-jzEiebBAn7uJhMyAxh77nsjqSUtNIvrdGFsXzKp8txVMqmdsjMuNA..; bai=360; login_sid_t=2aedb1fd26eea03d14da1916937ae80c; _s_tentry=-; UOR=,www.weibo.com,spr_sinamkt_buy_srwj1_weibo_t111; Apache=7890377011951.901.1482461705049; SINAGLOBAL=7890377011951.901.1482461705049; ULV=1482461705057:1:1:1:7890377011951.901.1482461705049:; TC-Page-G0=444eec11edc8886c2f0ba91990c33cda; TC-V5-G0=f88ad6a0154aa03e3d2a393c93b76575; WBStorage=2c466cc84b6dda21|undefined");
					method.addRequestHeader("Host", "weibo.com");
					method.addRequestHeader("Origin", "http://news.sohu.com/");
					method.addRequestHeader("Referer", "http://www.weibo.com/?category=1760");
					method.addRequestHeader("Upgrade-Insecure-Requests", "1");
					method.addRequestHeader("User-Agent",
							"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36");
					// 把请求头method文件发送过去,POST方法
					client.executeMethod(method);
					
				} catch (HttpException e) {
					e.printStackTrace();
				} catch (IOException e) {
					e.printStackTrace();
				}
				// 接收新浪返回的html文件,并把它存入content文件中
				content = method.getResponseBodyAsString();
				//把html文件写入到parser文件中
				parser.setInputHTML(content);
				
				//作者
				String authornode = getNewsAuthor(parser);
//				System.out.println("作者:"+authornode);
				//parser.reset()用于重置parser,不然每次使用之后就编程只有过滤后的代码
				parser.reset();
//				标题
				String titlenode = getTitle(parser);
//				System.out.println("标题:"+titlenode);
				parser.reset(); 
				String datenode = getdatelist(parser);
//				System.out.println("时间:"+datenode);
				parser.reset(); 
				String contentnode = getnewsContent(parser);
//				System.out.println("内容:"+contentnode);
				Map<String,String> map=new HashMap<String,String>();
				System.out.println(authornode);
				System.out.println(authornode);
				System.out.println(titlenode);
				System.out.println(datenode);
				map.put("内容:", contentnode);  
				map.put("作者:", authornode);    
				map.put("标题:",titlenode);    
				map.put("时间:", datenode);    
				return map;
	}

 那我就解释一下这个方法体:

1、首先要获取网址url。

HttpMethod method = new GetMethod(url);

2、因为要绕过新浪的防爬虫机制,所以写个请求头,最后再以post的方式发送出去,对应的方法是

client.executeMethod();

method.addRequestHeader("Accept",
							"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8");
method.addRequestHeader("Accept-Language", "zh-CN,zh;q=0.8");
method.addRequestHeader("Cache-Control", "no-cache");
method.addRequestHeader("Connection", "keep-alive");
method.addRequestHeader("Pragma", "no-cache");
method.addRequestHeader("Content-Type", "text/html; charset=UTF-8");
method.addRequestHeader("Cookie",
							"SCF=AuD5cb41vDeFJn-dHO9IrNlcTxq50vNxCCYhPUNxdhtrbUJEQJfxBkljP-8wVrATBTvovTuTFzt4y-mBLm4CYwk.; SUB=_2AkMvByHQdcNhrAJZnPsVzW3gZYlH-jzEiebBAn7uJhMyAxh77nsjqSUtNIvrdGFsXzKp8txVMqmdsjMuNA..; bai=360; login_sid_t=2aedb1fd26eea03d14da1916937ae80c; _s_tentry=-; UOR=,www.weibo.com,spr_sinamkt_buy_srwj1_weibo_t111; Apache=7890377011951.901.1482461705049; SINAGLOBAL=7890377011951.901.1482461705049; ULV=1482461705057:1:1:1:7890377011951.901.1482461705049:; TC-Page-G0=444eec11edc8886c2f0ba91990c33cda; TC-V5-G0=f88ad6a0154aa03e3d2a393c93b76575; WBStorage=2c466cc84b6dda21|undefined");
method.addRequestHeader("Host", "weibo.com");
method.addRequestHeader("Origin", "http://news.sohu.com/");
method.addRequestHeader("Referer", "http://www.weibo.com/?category=1760");
method.addRequestHeader("Upgrade-Insecure-Requests", "1");
method.addRequestHeader("User-Agent",
							"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36");
					// 把请求头method文件发送过去,POST方法
					client.executeMethod(method);

3、接受网址的返回结果,这时候就是页面的源码了。

Parser parser = new Parser();  //用于转存为htmlparser可操作的格式

// 接收新浪返回的html文件,并把它存入content文件中
				content = method.getResponseBodyAsString();
//把html文件写入到parser文件中
				parser.setInputHTML(content);

4、 解析html源码获取到自己想要的数据,一般是根据id来区分

				//作者
				String authornode = getNewsAuthor(parser);
				//parser.reset()用于重置parser,不然每次使用之后就编程只有过滤后的代码
				parser.reset();
//				标题
				String titlenode = getTitle(parser);
				parser.reset(); 
				String datenode = getdatelist(parser);
				parser.reset(); 
				String contentnode = getnewsContent(parser);
				Map<String,String> map=new HashMap<String,String>();
				map.put("内容:", contentnode);  
				map.put("作者:", authornode);    
				map.put("标题:",titlenode);    
				map.put("时间:", datenode);    
				return map;

我这里是存再map集合里面。

当然你要是存到一个类中或者一个其它集合中也可以的。

这里说一下,上面的那些方法是我自己写的过滤,你也可以根据自己的需要去写过滤器。

	//获取新闻作者	
	private static String getNewsAuthor( Parser parser) {
        String authornode = "";
        try {
        	//标签过滤器href="/u/5242412695"
            NodeList authorlist = parser.extractAllNodesThatMatch(new AndFilter(new TagNameFilter("a"), new HasAttributeFilter("class", "S_txt1")));
            TextExtractingVisitor visitor = new TextExtractingVisitor();
            authorlist.visitAllNodesWith(visitor);

            authornode = visitor.getExtractedText();
            authornode = authornode.replaceAll("\\s", "");
            
        } catch (ParserException ex) {
            Logger.getLogger(sinacrawlervoid.class.getName()).log(Level.SEVERE, null, ex);
        }
        return authornode;
    }

二、说一下,这个htmlparser一些接口的说明吧。

TextExtractingVisitor 这个类呢,是用来解析parser这个文本的,然后使用它的getExtractedText这个方法就能过滤掉其它的数据取得纯文本信息。

Node中包含的方法有几类:
对于树型结构进行遍历的函数,这些函数最容易理解:
Node getParent ():取得父节点
NodeList getChildren ():取得子节点的列表
Node getFirstChild ():取得第一个子节点
Node getLastChild ():取得最后一个子节点
Node getPreviousSibling ():取得前一个兄弟(不好意思,英文是兄弟姐妹,直译太麻烦而且不符合习惯,对不起女同胞了)
Node getNextSibling ():取得下一个兄弟节点

 

取得Node内容的函数
String getText ():取得文本
String toPlainTextString():取得纯文本信息。
String toHtml () :取得HTML信息(原始HTML)
String toHtml (boolean verbatim):取得HTML信息(原始HTML)
String toString ():取得字符串信息(原始HTML)
Page getPage ():取得这个Node对应的Page对象
int getStartPosition ():取得这个Node在HTML页面中的起始位置
int getEndPosition ():取得这个Node在HTML页面中的结束位置
用于Filter过滤的函数:
void collectInto (NodeList list, NodeFilter filter):基于filter的条件对于这个节点进行过滤,符合条件的节点放到list中。
用于Visitor遍历的函数:
void accept (NodeVisitor visitor):对这个Node应用visitor
用于修改内容的函数,这类用得比较少
void setPage (Page page):设置这个Node对应的Page对象
void setText (String text):设置文本
void setChildren (NodeList children):设置子节点列表
其他函数
void doSemanticAction ():执行这个Node对应的操作(只有少数Tag有对应的操作)
Object clone ():接口Clone的抽象函数。

要是有兴趣呢,可以下我工作前期写的工作项目集合。

https://download.csdn.net/download/fg676123/10906304

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值