新人国庆没事做,又研究了一下爬虫搜索,两三天时间总算是把原理闹的差不多了,基本实现了爬虫搜索的原理,本次实现还是俩程序,分别是按广度优先和深度优先完成的,广度优先没啥问题,深度优先请慎用,有极大的概率会造成死循环情况,下面深度优先的测试网站就造成了死循环。。。。好吧,我承认是我人品不太好。。。下面有请代码君出场~~~~~~~~~~~~~~~
1.广度优先
/**
* 完成广度优先搜索
*/
package net.meteor.java;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author 魏诗尧
* @version 1.8
* @emali [email protected]
*/
public class SearchCrawlerBreadth {
// 将网页源码下载到本地
private void downHTML(String urlstr, String htmltxt) {
// 声明链接
HttpURLConnection con = null;
// 声明输入流
InputStream in = null;
// 声明输出流
FileOutputStream out = null;
try {
// 实例化url
URL url = new URL(urlstr);
// 打开链接
con = (HttpURLConnection) url.openConnection();
con.connect();
// 打开输入流
in = con.getInputStream();
// 打开输出流创建接收文件
out = new FileOutputStream(htmltxt);
byte[] b = new byte[1024];
int len = 0;
// 将文件写入接收文件
while ((len = in.read(b, 0, 1024)) != -1) {
out.write(b, 0, len);
}
// 开始第二次爬行
new SearchCrawlerBreadth().readTxt("src/href.txt");
} catch (Exception e) {
System.out.println("未知主机!!");
} finally {
try {
// 关闭流
if (out != null)
out.close();
if (in != null)
in.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
// 页面解析
private void readTxt(String hreftxt) {
// 声明输入流
InputStream in = null;
FileWriter file = null;
BufferedReader br = null;
try {
// 实例化IO流,允许文件追加写
file = new FileWriter(hreftxt, true);
in = new FileInputStream("src/html.txt");
br = new BufferedReader(new InputStreamReader(in));
// 开始解析html
while (br.readLine() != null) {
String line = br.readLine();
// 创建正则表达式
Pattern pattern = Pattern.compile(
"]",
Pattern.CASE_INSENSITIVE);
// 创建匹配器
Matcher matcher = pattern.matcher(line);
// 开始与正则表达式进行匹配
while (matcher.find()) {
String str = matcher.group(1);
// 跳过链到本页面内链接和无效链接
if (str.length() < 1) {
continue;
}
if (str.charAt(0) == '#') {
continue;
}
if (str.startsWith("/")) {
continue;
}
if (str.indexOf("mailto:") != -1) {
continue;
}
if (str.toLowerCase().indexOf("javascript") != -1) {
continue;
}
if (str.startsWith("'")) {
continue;
}
// 将有效链接打印到屏幕
System.out.println(str);
// 将有效链接写入到文件
file.write(str + "\r\n");
}
}
} catch (Exception e) {
System.out.println("无效链接!!");
} finally {
// 关闭IO流
try {
if (file != null)
file.close();
if (br != null)
br.close();
if (in != null)
in.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
// 进行深度搜索
private void search() {
// 声明IO流
InputStream in = null;
BufferedReader br = null;
try {
// 实例化IO流
in = new FileInputStream("src/href.txt");
br = new BufferedReader(new InputStreamReader(in));
// 创建SearchCrawler的对象
SearchCrawlerBreadth sc = new SearchCrawlerBreadth();
// 开始按行读取有效链接的文件
while (br.readLine() != null) {
String line = br.readLine();
// 递归调用爬虫爬行页面
sc.downHTML(line, "src/html.txt");
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
// 关闭流
if (br != null)
br.close();
if (in != null)
in.close();
} catch (Exception e2) {
e2.printStackTrace();
}
}
}
public static void main(String[] args) throws Exception {
// 传入要爬行的页面和保存HTML源码的文件地址
new SearchCrawlerBreadth().downHTML("http://www.hao123.com/", "src/html.txt");
// 调用第二次的搜索
new SearchCrawlerBreadth().search();
}
}
下面是深度优先的代码,测试的时候每次都能造成死循环。。。好吧,我承认我没有人品。。。其实基本方法和广度优先没啥区别,我每个页面爬出来的链接只拿第一个去爬下一个页面,总共爬多少层我懒的木有定义,就是想看看最多能爬到哪。。。然后每次都能悲剧的死循环了。。。我明明也设置了跳出的方法了啊,我有判断有效链接的方式,但是我的判断并不完善么,跳出方法我写到了catch中,只要有一个无效链接,就可以跳出来了么。。。今天凌晨全都是死循环。。。。无奈了。。。。下面请代码君上场~~~~~~~~~~
/**
* 完成深度优先搜索
* 爬虫进行深度优先很有可能会出现死循环的情况
*/
package net.meteor.java;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashSet;
import java.util.Iterator;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author 魏诗尧
* @version 1.8
* @emali [email protected]
*/
public class SearchCrawlerDepth {
// 声明一个静态集合,用来存放爬虫爬到的URL
private static HashSet set = new HashSet();
// 将网页源码下载到本地
private void downHTMLDepth(String urlstr, String htmltxt) {
// 声明链接
HttpURLConnection con = null;
// 声明输入流
InputStream in = null;
// 声明输出流
FileOutputStream out = null;
try {
// 实例化url
URL url = new URL(urlstr);
// 打开链接
con = (HttpURLConnection) url.openConnection();
con.connect();
// 打开输入流
in = con.getInputStream();
// 打开输出流创建接收文件
out = new FileOutputStream(htmltxt);
byte[] b = new byte[1024];
int len = 0;
// 将文件写入接收文件
while ((len = in.read(b, 0, 1024)) != -1) {
out.write(b, 0, len);
}
new SearchCrawlerDepth().readTxtDepth("src/hrefdepth.txt");
} catch (Exception e) {
System.out.println("未知主机!!,爬行结束!!");
} finally {
try {
// 关闭流
if (out != null)
out.close();
if (in != null)
in.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
// 页面解析
private void readTxtDepth(String hreftxt) {
// 声明输入流
InputStream in = null;
BufferedReader br = null;
try {
// 实例化IO流,允许文件追加写
in = new FileInputStream("src/htmldepth1.txt");
br = new BufferedReader(new InputStreamReader(in));
// 开始解析html
A: while (br.readLine() != null) {
String line = br.readLine();
// 创建正则表达式
Pattern pattern = Pattern.compile(
"]",
Pattern.CASE_INSENSITIVE);
// 创建匹配器
Matcher matcher = pattern.matcher(line);
// 开始与正则表达式进行匹配
while (matcher.find()) {
String str = matcher.group(1);
// 跳过链到本页面内链接和无效链接
if (str.length() < 1) {
continue;
}
if (str.charAt(0) == '#') {
continue;
}
if (str.startsWith("/")) {
continue;
}
if (str.indexOf("mailto:") != -1) {
continue;
}
if (str.toLowerCase().indexOf("javascript") != -1) {
continue;
}
if (str.startsWith("'")) {
continue;
}
// 将有效链接打印到屏幕
System.out.println(str);
// 将第一个有效链接写入到hashset
while (str != null) {
set.add(str);
new SearchCrawlerDepth().downHTMLDepth(str, "src/htmldepth1.txt");
break A;
}
}
}
} catch (Exception e) {
System.out.println("无效链接!!本次爬行结束!!");
new SearchCrawlerDepth().searchDepth();
} finally {
// 关闭IO流
try {
if (br != null)
br.close();
if (in != null)
in.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
public void searchDepth() {
FileWriter file = null;
try {
// 声明文件路径,可以追加写
file = new FileWriter("src/hrefdepth1.txt", true);
// 用迭代器遍历得到链接
Iterator it = set.iterator();
while (it.hasNext()) {
System.out.println(it);
file.write(it + "\r\n");
}
} catch (IOException e) {
System.out.println("无效链接,本次爬行结束!!");
e.printStackTrace();
} finally {
try {
if (file != null)
file.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
new SearchCrawlerDepth().downHTMLDepth("http://www.hao123.com", "src/htmldepth1.txt");
new SearchCrawlerDepth().searchDepth();
}
}