java简易的贴吧邮箱爬虫

小黄我老早就听说过爬虫大名了,可是却一直没有敢于尝试,这回因为脑子一热,断断续续的研究了几天,没想到并没有想象中的那么难,当然,我做的仅仅是最简单最初级的爬虫,但至少拥有爬虫大致之型了吧。总之,任何高超复杂的技术,都是从最简单开始逐步完善的,所以在技术的路上,我们应该无所畏惧,敢于尝试。好了,废话不多说了,进入正题。

  准备工作:使用了开源包HttpClient(使用方法和下载自己百度)

  大体流程:1,初始化(获取url装入url队列)。 2,判定条件(url队列中url的限定个数)。 3,如果满足条件,通过队列中的url连接网页并下载 。4,抓取解析邮箱与url。 5,将邮箱保存在本地txt文件中。


流程大致就是上面的。

下面来看看代码:

注:本爬虫专门爬取贴吧中的邮箱,所以输入的url仅限为所选贴吧的首页,它会自动爬取首页中帖子里包含的邮箱的。

各个类以及源码:

类的主要

Crawler.java:爬虫的主方法入口所在的类,实现爬取的主要流程。

LinkDB.java:保存已访问url和未访问url的类,提供出入队的操作。

Queue.java:一个简单的队列,LinkDB实现它。

InternetConnect.java:用get方式连接网页,并下载。

HtmlParse.java:抓取下载下来的网页中url与邮箱的。

FileSave.java:抓取的邮箱的本地存储。


源码:

1.Crawler

import java.util.HashSet;
import java.util.Set;

//爬虫的主操作
public class Crawler {
	private Set<String> emails = new HashSet<String>();
	int num =0;
	//爬取网页中的url
	private void initCrawler(String url){
		Set<String> set = HtmlParse.getUrl(url);
		for(String s:set){
			LinkDB.addUnvisitedUrl(s);
		}
	}
	public void crawling(String url){
		initCrawler(url);
		//判定条件
		while(!LinkDB.unVisitedUrlsEmpty()&&LinkDB.getVisitedUrlNum()<=100){
			//队头出Url
			String visitUrl = LinkDB.unVisitedUrlDeQueue();
			//在控制台显示所爬url
			System.out.println(visitUrl);
			num++;
			if(visitUrl==null)
				continue;
			LinkDB.addVisitedUrl(visitUrl);
			Set<String> email = HtmlParse.getEmail(visitUrl);
			emails.addAll(email);
			initCrawler(visitUrl);
		}
		for(String s:emails){
			System.out.println(s);
		}
		FileSave.fileSave(emails);
		System.out.println("网页个数"+num);
		System.out.println("邮箱个数"+emails.size());
		
	}
	public static void main(String[] args) {
		//输入想要爬取的url,记住一定得是所选贴吧的首页(这个是邮箱吧)
		new Crawler().crawling("http://tieba.baidu.com/f?kw=%D3%CA%CF%E4&fr=ala0");

	}

}


2.LinkDB

import java.util.HashSet;
import java.util.Set;
//一般步骤为:定义数据结构及其操作
public class LinkDB {
	//已访问的url
	private static Set<String> visitedUrl = new HashSet<String>();
	//未访问的url
	private static Queue<String> unVisitedUrl = new Queue<String>();
	
	public static Queue<String> getUnVisitedUrl(){
		return unVisitedUrl;
	}
	
	public static void addVisitedUrl(String url){
		visitedUrl.add(url);
	}
	
	public static void removeVisitedUrl(String url){
		visitedUrl.remove(url);
	}
	
	public static String unVisitedUrlDeQueue(){
		return unVisitedUrl.deQueue();
	}
	//确定每个url只访问过一次
	public static void addUnvisitedUrl(String url){
		if(url !=null&&!url.trim().equals("")&&!visitedUrl.contains(url)&&!unVisitedUrl.contains(url))
			unVisitedUrl.enQueue(url);
	}
	
	public static int getVisitedUrlNum(){
		return visitedUrl.size();
	}
	
	public static boolean unVisitedUrlsEmpty(){
		return unVisitedUrl.isQueueEmpty();
	}
	

}

3.Queue.java

import java.util.LinkedList;
//数据结构队列,用LinkedList来实现 T是泛型,可自定义传入的泛型
public class Queue<T> {
	private LinkedList<T> queue = new LinkedList<T>();
	//队列中加操作
	public void enQueue(T t){
		queue.add(t);
	}
	//删除第一个,并提取出来
	public T deQueue(){
		return queue.removeFirst();
	}
	public boolean isQueueEmpty(){
		return queue.isEmpty();
	}
	public boolean contains(T t){
		return queue.contains(t);
	}
}

4.HtmlParse.java
这个我绝对要吐槽一下,我以为正则表达式很简单,结果,我擦。。。。默泪中......小黄真是学艺不精啊,搞了很久,郁闷至极中百度的帖子的url又不按正常的来,于是顺带擦一下.....嘿嘿。(吐槽勿怪,赶紧贴代码)

import java.util.HashSet;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class HtmlParse {
	//抓取网页中的url
	public static Set<String> getUrl(String url){
		Set<String> set = new HashSet<String>();
		//抓取url的正则表达式,小黄学艺不精,各位看官将就看吧
		Pattern pattern = Pattern.compile("<\\s*a\\s*href\\s*=\\s*\"/p/([^\"]+)");
		try{
			
			Matcher matcher = pattern.matcher(InternetConnect.getRequst(url));
			while(matcher.find()){
				//帖子的url太简略了,还得我来加.....
				set.add(matcher.group().replaceAll("<a href=\"", "http://tieba.baidu.com"));
				}
			
			}catch(Exception e){
				e.printStackTrace();
			}
		return set;
	}
	//抓取网页中的邮箱
	public static Set<String> getEmail(String url){
		//用Set集合,去掉重复邮箱
		Set<String> set = new HashSet<String>();
		Pattern pattern = Pattern.compile("[\\w\\.\\-]+@([\\w\\-]+\\.)+[\\w\\-]+");
		try{
			
			Matcher matcher = pattern.matcher(InternetConnect.getRequst(url));
			while(matcher.find()){
				set.add(matcher.group());
				}
			
			}catch(Exception e){
				e.printStackTrace();
			}
		return set;
	}

}

5,FileSave.java

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Set;

public class FileSave {
	//保存到指定txt
	public static void fileSave(Set<String> set){
		//读取当前时间来当做文件名
		Date date =new Date();
		SimpleDateFormat dateFormat =new SimpleDateFormat("yyyyMMddHHmm");
		System.out.println("存放的txt名为"+dateFormat.format(date)+"email.txt");
		try{
		File file = new File(dateFormat.format(date)+"email.txt");
		BufferedWriter writer =new BufferedWriter(new FileWriter(file));
		for(String s:set){
			//换行得是\r\n
			writer.write(s+"\r\n");
		}
		writer.close();
		}catch(IOException ex){
			ex.printStackTrace();
		}
		
	}
}


6,InternetConnect

import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;

/*
 * 连接网页,下载网页
 * get通信
 */
public class InternetConnect {
	static HttpClient httpClient;
	public static String getRequst(String url) throws Exception{
		httpClient = new DefaultHttpClient();
		try{
			//使用get方式连接,得到回应,如果状态码为200则...自己看代码
			HttpGet get = new HttpGet(url);
			
			HttpResponse httpResponse = httpClient.execute(get);
			
			if(httpResponse.getStatusLine().getStatusCode()==200){
				//以字符串形式获取网页源码
				String result = EntityUtils.toString(httpResponse.getEntity());
				return result;
			}
		}catch(Exception e){
			e.printStackTrace();
			return"worry";}finally{
	//妈妈曾经告诉我..好吧,是老师,画虚线的方法都是老的要被淘汰的,但这个是我以前做项目时辛苦收藏的,于是坚持用。
				httpClient.getConnectionManager().shutdown();
			}
		return null;
	}
}


好啦,代码就是上面这些。
我写这篇文章主要参考了:https://www.ibm.com/developerworks/cn/opensource/os-cn-crawler/
这是我花大量时间唯一找到的详细写了爬虫的而且令人满意的博文,在此十分感谢作者,欢迎大家去看看




其实嘛,我这个只是1.0,后续可扩展的功能十分多,比如给所爬取的邮箱发邮件啊(慎用,有被骂的风险);抓取友情贴吧的邮箱啊等等......如果继续坚持下去的话,肯定能写出一个复杂高超的爬虫的,哈哈哈
好勒,大致本文结束了,这是小黄写的第一篇博客,再加上水平有限,有很多不足之处望大家指出批判,很希望与大家能进行讨论,只有分享与讨论才能更好的进步嘛 。下一步,学着把源代码传到GitHub上(好吧,小黄弱爆了,连GitHub都没用过),还望大家能指导。


评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值