本帖最后由 nettman 于 2015-4-16 22:37 编辑
问题导读:
1、CrawlListPageBase类功能是什么?
2、用HttpClient 模拟浏览器的行为,如何对请求做伪装?
3、获取页面内我们需要的链接?
接上篇:基于lucene的案例开发17:查询语句创建PackQuery
之前的博客,已经介绍了如何基于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类还请访问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 ,对页面做简单的分析即可发现下图中的内容就是最新更新的小说书目列表。
通过鼠标右键--查看网页源代码 不难找到这些数据在网页中的位置,如下图:
而红色框出来的内容就是我们需要的下一跳网址,因此我们可以很简单的确定获取该信息的正则表达式是 : <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;
- }
复制代码
我们使用上述方法代替之前说的那个方法即可选择是否舍弃这些网址,在这个项目中,我们选择舍弃。经过上述步骤,纵横中文的更新列表页的采集模版就完成了。
运行结果
源代码 最新源代码可以访问: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);
- }
- }
- }
-
-
复制代码
相关内容:
基于lucene的案例开发1:lucene初始认知
基于lucene的案例开发2:索引数学模型
基于lucene的案例开发3:索引文件结构
基于lucene的案例开发4:创建索引
基于lucene的案例开发5:搜索索引
基于lucene的案例开发6:分词器介绍
基于lucene的案例开发7:Query查询
基于lucene的案例开发8:IndexSearcher中检索方法
基于lucene的案例开发9:案例初识
基于lucene的案例开发10:搜索后台基础,JsonUtil & XmlUtil类介绍
基于lucene的案例开发11:项目常用类ClassUtil & CharsetUtil介绍
基于lucene的案例开发12:数据库连接池
基于lucene的案例开发13:实现实时索引基本原理
基于lucene的案例开发14:实时索引管理类IndexManager
基于lucene的案例开发15:实时索引的检索
基于lucene的案例开发16:实时索引的修改
基于lucene的案例开发17:查询语句创建PackQuery
基于lucene的案例开发18:纵横小说更新列表页抓取
基于lucene的案例开发19:纵横小说简介页采集
基于lucene的案例开发20:纵横小说章节列表采集
基于lucene的案例开发21:纵横小说阅读页采集
资料来源:http://blog.csdn.net/xiaojimanman/article/details/44831003
|