截止目前,已完成如下功能:

1、指定某个地址,使用HttpClient下载该网页至本地文件

2、使用HtmlParser解释第1步下载的网页,抽取其中包含的链接信息

3、下载第2步的所有链接指向的网页至本地文件

下一步需要完成的功能:

1、创建用于保存种子URL的配置文件及其数据结构

2、创建用于保存Todo信息(未下载URL)的数据结构

3、创建用于保存Visited信息(已下载的URL)的数据结构

4、下载网页时同步更新Tode与Visited。

5、从上述第3步下载的网页抽取链接并继续下载,直到Todo列表为空。

主要有以下类:

1、主类MyCrawler

2、网页下载类PageDownloader

3、网页内容分类类HtmlParserTool

4、接口Filter

完整代码可见归档代码 Jediael_v0.01

或者

https://code.csdn.net/jediael_lu/daopattern/tree/d196da609baa59ef08176322ca61928fbfbdf813

或者

http://download.csdn.net/download/jediael_lu/7382011

1、主类MyCrawler

package org.ljh.search;

import java.io.IOException;
import java.util.Iterator;
import java.util.Set; import org.htmlparser.Parser;
import org.ljh.search.downloadpage.PageDownloader;
import org.ljh.search.html.HtmlParserTool;
import org.ljh.search.html.LinkFilter; public class MyCrawler { public static void main(String[] args) {
String url = "http://www.baidu.com"; LinkFilter linkFilter = new LinkFilter(){
@Override
public boolean accept(String url) {
if(url.contains("baidu")){
return true;
}else{
return false;
}
}
};
try {
PageDownloader.downloadPageByGetMethod(url);
Set<String> urlSet = HtmlParserTool.extractLinks(url, linkFilter);
Iterator iterator = urlSet.iterator();
while(iterator.hasNext()){
PageDownloader.downloadPageByGetMethod((String) iterator.next());
} } catch (Exception e) {
e.printStackTrace();
}
} }

2、网页下载类PageDownloader

package org.ljh.search.downloadpage;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.Writer;
import java.util.Scanner; import org.apache.http.HttpEntity;
import org.apache.http.HttpStatus;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients; //本类用于将指定url对应的网页下载至本地一个文件。
public class PageDownloader { public static void downloadPageByGetMethod(String url) throws IOException { // 1、通过HttpGet获取到response对象
CloseableHttpClient httpClient = HttpClients.createDefault();
// 注意,必需要加上http://的前缀,否则会报:Target host is null异常。
HttpGet httpGet = new HttpGet(url);
CloseableHttpResponse response = httpClient.execute(httpGet); InputStream is = null;
if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
try {
// 2、获取response的entity。
HttpEntity entity = response.getEntity(); // 3、获取到InputStream对象,并对内容进行处理
is = entity.getContent(); String fileName = getFileName(url);
saveToFile("D:\\tmp\\", fileName, is);
} catch (ClientProtocolException e) {
e.printStackTrace();
} finally { if (is != null) {
is.close();
}
if (response != null) {
response.close();
}
}
}
} //将输入流中的内容输出到path指定的路径,fileName指定的文件名
private static void saveToFile(String path, String fileName, InputStream is) {
Scanner sc = new Scanner(is);
Writer os = null;
try {
os = new PrintWriter(path + fileName);
while (sc.hasNext()) {
os.write(sc.nextLine());
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (sc != null) {
sc.close();
}
if (os != null) {
try{
os.flush();
os.close();
}catch(IOException e){
e.printStackTrace();
System.out.println("输出流关闭失败!");
}
}
}
} // 将url中的特殊字符用下划线代替
private static String getFileName(String url) {
url = url.substring(7);
String fileName = url.replaceAll("[\\?:*|<>\"/]", "_") + ".html";
return fileName;
} }

3、网页内容分类类HtmlParserTool

package org.ljh.search.html;

import java.util.HashSet;
import java.util.Set; import org.htmlparser.Node;
import org.htmlparser.NodeFilter;
import org.htmlparser.Parser;
import org.htmlparser.filters.NodeClassFilter;
import org.htmlparser.filters.OrFilter;
import org.htmlparser.tags.LinkTag;
import org.htmlparser.util.NodeList;
import org.htmlparser.util.ParserException; //本类创建用于HTML文件解释工具
public class HtmlParserTool { // 本方法用于提取某个html文档中内嵌的链接
public static Set<String> extractLinks(String url, LinkFilter filter) {
Set<String> links = new HashSet<String>();
try {
// 1、构造一个Parser,并设置相关的属性
Parser parser = new Parser(url);
parser.setEncoding("gb2312"); // 2.1、自定义一个Filter,用于过滤<Frame >标签,然后取得标签中的src属性值
NodeFilter frameNodeFilter = new NodeFilter() {
@Override
public boolean accept(Node node) {
if (node.getText().startsWith("frame src=")) {
return true;
} else {
return false;
}
}
}; //2.2、创建第二个Filter,过滤<a>标签
NodeFilter aNodeFilter = new NodeClassFilter(LinkTag.class); //2.3、净土上述2个Filter形成一个组合逻辑Filter。
OrFilter linkFilter = new OrFilter(frameNodeFilter, aNodeFilter); //3、使用parser根据filter来取得所有符合条件的节点
NodeList nodeList = parser.extractAllNodesThatMatch(linkFilter); //4、对取得的Node进行处理
for(int i = 0; i<nodeList.size();i++){
Node node = nodeList.elementAt(i);
String linkURL = "";
//如果链接类型为<a />
if(node instanceof LinkTag){
LinkTag link = (LinkTag)node;
linkURL= link.getLink();
}else{
//如果类型为<frame />
String nodeText = node.getText();
int beginPosition = nodeText.indexOf("src=");
nodeText = nodeText.substring(beginPosition);
int endPosition = nodeText.indexOf(" ");
if(endPosition == -1){
endPosition = nodeText.indexOf(">");
}
linkURL = nodeText.substring(5, endPosition - 1);
}
//判断是否属于本次搜索范围的url
if(filter.accept(linkURL)){
links.add(linkURL);
}
} } catch (ParserException e) {
e.printStackTrace();
}
return links;
}
}

4、接口Filter

package org.ljh.search.html;

//本接口所定义的过滤器,用于判断url是否属于本次搜索范围。
public interface LinkFilter {
public boolean accept(String url);
}

【搜索引擎Jediael开发4】V0.01完整代码的更多相关文章

  1. 【搜索引擎Jediael开发4】V0.01完整代码 分类: H_HISTORY 2014-05-21 21:35 470人阅读 评论(0) 收藏

    截止目前,已完成如下功能: 1.指定某个地址,使用HttpClient下载该网页至本地文件 2.使用HtmlParser解释第1步下载的网页,抽取其中包含的链接信息 3.下载第2步的所有链接指向的网页 ...

  2. 【搜索引擎Jediael开发笔记1】搜索引擎初步介绍及网络爬虫

    详细可参考 (1)书箱:<这就是搜索引擎><自己动手写网络爬虫><解密搜索引擎打桩实践> (2)[搜索引擎基础知识1]搜索引擎的技术架构 (3)[搜索引擎基础知识2 ...

  3. 【搜索引擎Jediael开发笔记】v0.1完整代码

    详细代码请见 E:\Project\[重要]归档代码\SearchEngine归档代码 或 https://code.csdn.net/jediael_lu/jediael/tree/10991c83 ...

  4. 【搜索引擎Jediael开发笔记】v0.1完整代码 2014-05-26 15:17 463人阅读 评论(0) 收藏

    详细代码请见 E:\Project\[重要]归档代码\SearchEngine归档代码 或 https://code.csdn.net/jediael_lu/jediael/tree/10991c83 ...

  5. 【搜索引擎Jediael开发笔记】V0.1完整代码 2014-05-26 15:16 443人阅读 评论(0) 收藏

    详细代码请见 E:\Project\[重要]归档代码\SearchEngine归档代码 或 https://code.csdn.net/jediael_lu/jediael/tree/10991c83 ...

  6. 【搜索引擎Jediael开发笔记3】使用HtmlParser提取网页中的链接

    关于HtmpParser的基本内容请见 HtmlParser基础教程 本文示例用于提取HTML文件中的链接 package org.ljh.search.html; import java.util. ...

  7. 【搜索引擎Jediael开发笔记2】使用HttpClient下载网页至本地文件

    本文使用HttpClient根据url进行网页下载.其中 (1)HttpClient的相关知识请参见HttpClient基础教程 (2) package org.ljh.search.download ...

  8. VM架构设计文档初稿v0.01

    VM架构设计文档初稿v0.01 文档介绍 本文档是经过讨论,作为VM新架构设计开发中的重要依据.对该架构的整个系统的结构进行详实细致的描述.阐述框架结构,说明该架构所采取的设计策略和所有技术,并对相关 ...

  9. 【5】TensorFlow光速入门-图片分类完整代码

    本文地址:https://www.cnblogs.com/tujia/p/13862364.html 系列文章: [0]TensorFlow光速入门-序 [1]TensorFlow光速入门-tenso ...

随机推荐

  1. TexturePacker文件的反向解析-TextureUnpacker

    最近在使用cocos2d-x做开发,其中会用到TexturePacker工具打包纹理文件,但是有时候想从打包好的.plist和.png大图文件反向生成原始的小图文件,TexturePacker好像没有 ...

  2. java程序的10个调试技巧

    参看下面链接:http://www.kuqin.com/java/20120906/330130.html

  3. 极客”一词,来自于美国俚语“geek”的音译,一般理解为性格古怪的人

    起源 “ 极客”一词,来自于美国俚语“ geek”的音译,一般理解为性格古怪的人.数学“极客”大多是指,并不 一定是数学专业但又对数学等技术有狂热的兴趣并投入大量时间钻研的人.又 译作“ 奇客”.以前 ...

  4. JavaScript 全局变量命名空间生成函数

    <script type="text/javascript"> var GLOBAL = {}; GLOBAL.namespace = function(str){ v ...

  5. 使用Spring Boot和Gradle创建AngularJS项目

    Spring Boot 是由 Pivotal 团队提供的全新框架,其设计目的是用来简化新 Spring 应用的初始搭建以及开发过程.该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的 ...

  6. NOI十连测 第五测 T1

    #include<cstdio> #include<cstring> #include<cmath> #include<iostream> #inclu ...

  7. 把所有的QT的类都过一遍脑子

    http://doc.qt.io/qt-5/classes.html 这样就明白QT提供的全部功能了,避免重复造轮子,或者给自己开发带来麻烦-

  8. T-SQL 脚本

    1.USE语句 USE语句用于设置当前数据库,如果没有USE语句,那么就由执行脚本的任何用户来确定执行脚本时当前数据库是正确的.如果只是一个通用脚本,那么省去USE语句实际上可能更有益.通常,如果在脚 ...

  9. java数组复制的方式和效率比较

    java中,数组的复制有以下三种方式: 1. 调用System.arraycopy(Arrays.copyOfRange可以当作第四种,但是底层调用的是System.arraycopy,所以,认为是同 ...

  10. ios的一些开源资源

    1. http://www.open-open.com/lib/view/open1428646127375.html vim插件:https://github.com/Valloric/YouCom ...