牛骨文教育服务平台(让学习变的简单)

转载请注明出处:http://blog.csdn.net/xiaojimanman/article/details/44831003

http://www.llwjy.com/blogdetail/a2d1df2b69f17696865f086777996fb1.html

个人博客站已经上线了,网址 www.llwjy.com ~欢迎各位吐槽~


之前的博客,已经介绍了如何基于Lucene来开发站内搜索的大部分内容,剩下的就是一些业务逻辑部分的开发以及接口的定义,这一部分在数据采集介绍完毕之后再来介绍。如果你已经对网络爬虫已经相当熟悉,可以忽略之后的几篇博客~

在之前的博客《基于HttpClient实现网络爬虫~以百度新闻为例》对自己的爬虫底层实现以及如何分析网页结构,抓取网页内容做了部分介绍,对之前介绍过的内容就不再过多介绍了,下面就重点说一下最新底层更新情况。

CrawlBase

在之前的CrawlBase类中,自己是这样定义HttpClient的,这样带来的后果就是在多线程的情况下会出现一系列的问题,所以对HttpClient的定义做了如下修改:

修改前:

private static HttpClient httpClient = new HttpClient();

修改后:

private static MultiThreadedHttpConnectionManager httpConnectionManager = new MultiThreadedHttpConnectionManager();
private static HttpClient httpClient = new HttpClient(httpConnectionManager);

同时还支持手动输入网址含有中文,通过CrawlListPageBase类获取的下一跳的网址是不会出现该问题的。具体的修改是对URL做一次处理,具体方法如下:

private String encodeUrlCh(String url) {
	try {
		return DoRegex.encodeUrlCh(url);
	} catch (UnsupportedEncodingException e) {
		e.printStackTrace();
		return url;
	}
}

其他应该没有太多的修改,最新的CrawlBase类还请访问http://www.llwjy.com/source/com.lulei.crawl.CrawlBase.html
ps:要获取个人最新java源代码,请访问http://www.llwjy.com/source.html,只需要在输入框内输入引用的类,即可检索出最新源码,比如:输入 com.lulei.crawl.CrawlBase 即可查看 CrawlBase 类的相信信息。

CrawlListPageBase

CrawlListPageBase类是自己对更新列表这一类的网页做的一次封装,从网页中只获取下一跳的网址。下面就按照纵横中文小说网站的实际情况来介绍如何使用CrawlListPageBase类来实现更新列表页信息的获取。

访问纵横中文网,可以很容易的就找到免费小说的更新列表页,网址:http://book.zongheng.com/store/c0/c0/b9/u0/p1/v0/s9/t0/ALL.html ,对页面做简单的分析即可发现下图中的内容就是最新更新的小说书目列表。

img

通过鼠标右键--查看网页源代码  不难找到这些数据在网页中的位置,如下图:

img

而红色框出来的内容就是我们需要的下一跳网址,因此我们可以很简单的确定获取该信息的正则表达式是 : <a class="fs14" href="(.*?)" ,因此我们需要创建CrawlListPageBase的一个子类UpdateList,让它来完成纵横免费小说更新列表页信息的采集,对CrawlListPageBase类中的抽象方法做具体的实现,如下:

@Override
public String getUrlRegexString() {
	return "<a class="fs14" href="(.*?)"";
}

@Override
public int getUrlRegexStringNum() {
	return 1;
}

用HttpClient 模拟浏览器的行为,需要对请求做一点伪装,由于纵横的防爬虫策略做的并不是太好,所以只需要做Referer和User-Agent即可,具体如下:

private static HashMap<String, String> params;
/**
 * 添加相关头信息,对请求进行伪装
 */
static {
	params = new HashMap<String, String>();
	params.put("Referer", "http://book.zongheng.com");
	params.put("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.125 Safari/537.36");
}

在添加构造方法时,只需要使用params即可,如下:

public UpdateList(String urlStr) throws IOException {
	super(urlStr, "utf-8", params);  
}

这样UpdateList子类计算完成了,使用getPageUrls()方法即可获取页面内我们需要的链接。

经过众多数据的测试,这时候你不难发现,纵横中文网的更新列表上的数目并不是全部来自纵横中文网,还有其他的站,因此需要对这些数据做简单的过滤,代码如下:

public List<String> getPageUrls(boolean exceptOther){
	List<String> urls = getPageUrls();
	if (exceptOther) {
		List<String> exceptUrls = new ArrayList<String>();
		for (String url : urls) {
			if (url.indexOf("zongheng") > 0) {
				exceptUrls.add(url);
			}
		}
		return exceptUrls;
	}
	return urls;
}

我们使用上述方法代替之前说的那个方法即可选择是否舍弃这些网址,在这个项目中,我们选择舍弃。经过上述步骤,纵横中文的更新列表页的采集模版就完成了。

运行结果

img

源代码

最新源代码可以访问:http://www.llwjy.com/source/com.lulei.crawl.novel.zongheng.UpdateList.html

 /**  
 *@Description:   更新列表页
 */ 
package com.lulei.crawl.novel.zongheng;  

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import com.lulei.crawl.CrawlListPageBase;
  
public class UpdateList  extends CrawlListPageBase{
	
	private static HashMap<String, String> params;
	/**
	 * 添加相关头信息,对请求进行伪装
	 */
	static {
		params = new HashMap<String, String>();
		params.put("Referer", "http://book.zongheng.com");
		params.put("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.125 Safari/537.36");
	}

	public UpdateList(String urlStr) throws IOException {
		super(urlStr, "utf-8", params);  
	}

	@Override
	public String getUrlRegexString() {
		return "<a class="fs14" href="(.*?)"";
	}

	@Override
	public int getUrlRegexStringNum() {
		return 1;
	}
	
	/**
	 * @param exceptOther
	 * @return
	 * @Author:lulei  
	 * @Description: 是否排除非纵横的书籍
	 */
	public List<String> getPageUrls(boolean exceptOther){
		List<String> urls = getPageUrls();
		if (exceptOther) {
			List<String> exceptUrls = new ArrayList<String>();
			for (String url : urls) {
				if (url.indexOf("zongheng") > 0) {
					exceptUrls.add(url);
				}
			}
			return exceptUrls;
		}
		return urls;
	}

	public static void main(String[] args) throws IOException {
		// TODO Auto-generated method stub  
		UpdateList updateList = new UpdateList("http://book.zongheng.com/store/c0/c0/b9/u0/p1/v0/s9/t0/ALL.html");
		for (String s : updateList.getPageUrls(true)) {
			System.out.println(s);
		}
	}
}


ps:最近发现其他网站可能会对博客转载,上面并没有源链接,如想查看更多关于 基于lucene的案例开发点击这里。或访问网址http://blog.csdn.net/xiaojimanman/article/category/2841877