几个简单网络爬虫的例子--还没验证

一个简单的java网络爬虫,由于时间原因,没有进一步解释.

需要的htmlparser.jar包到官方网上去下.

 

  1. ---------------------------------------------Spider.java-----------------------------------------------------------------


  2. import java.io.BufferedReader;
  3. import java.io.InputStreamReader;
  4. import java.net.URL;
  5. import java.net.URLConnection;
  6. import java.util.ArrayList;
  7. import java.util.HashMap;
  8. import java.util.Iterator;
  9. import java.util.List;
  10. import org.htmlparser.RemarkNode;
  11. import org.htmlparser.StringNode;
  12. import org.htmlparser.Node;
  13. import org.htmlparser.tags.*;
  14. import org.htmlparser.Parser;
  15. import org.htmlparser.filters.StringFilter;
  16. import org.htmlparser.util.NodeIterator;
  17. import org.htmlparser.util.NodeList;
  18. import org.htmlparser.util.ParserException;
  19. import java.util.Queue;
  20. import java.util.LinkedList;

  21. public class Spider implements Runnable {

  22. boolean search_key_words = false;

  23. int count = 0;

  24. int limitsite = 10;

  25. int countsite = 1;

  26. String keyword = "中国";//搜索关键字

  27. Parser parser = new Parser();

  28. // List linklist = new ArrayList();
  29. String startsite = "";//搜索的其实站点

  30. SearchResultBean srb;//保存搜索结果

  31. List resultlist = new ArrayList();//搜索到关键字链接列表

  32. List searchedsite = new ArrayList();//已经被搜索站点列表

  33. Queue linklist = new LinkedList();//需解析的链接列表

  34. HashMap> disallowListCache = new HashMap>();

  35. public Spider(String keyword, String startsite) {
  36.    this.keyword = keyword;
  37.    this.startsite = startsite;
  38.    linklist.add(startsite);
  39.    srb = new SearchResultBean();
  40. }

  41. public void run() {
  42.    // TODO Auto-generated method stub
  43.    search(linklist);

  44. }

  45. public void search(Queue queue) {
  46.    String url = "";
  47.      while(!queue.isEmpty()){
  48.     url = queue.peek().toString();//查找列队
  49.     try {
  50.      if (!isSearched(searchedsite, url)) {
  51.       if (isRobotAllowed(new URL(url)))//检查该链接是否被允许搜索
  52.        processHtml(url);
  53.       else
  54.        System.out.println("this page is disallowed to search");
  55.      }
  56.     } catch (Exception ex) {

  57.     }
  58.     queue.remove();
  59.   
  60.      }
  61.     
  62. }
  63. /**
  64. * 解析HTML
  65. * @param url 
  66. * @throws ParserException
  67. * @throws Exception
  68. */
  69. public void processHtml(String url) throws ParserException, Exception {
  70.    searchedsite.add(url);
  71.    count = 0;
  72.    System.out.println("searching ... :" + url);
  73.    parser.setURL(url);
  74.    parser.setEncoding("GBK");
  75.    URLConnection uc = parser.getConnection();
  76.    uc.connect();
  77.    //uc.getLastModified();
  78.    NodeIterator nit = parser.elements();
  79.   
  80.    while (nit.hasMoreNodes()) {
  81.     Node node = nit.nextNode();
  82.     parserNode(node);
  83.    }
  84.    srb.setKeywords(keyword);
  85.    srb.setUrl(url);
  86.    srb.setCount_key_words(count);
  87.    resultlist.add(srb);
  88.    System.out.println("count keywords is :" + count);
  89.    System.out.println("----------------------------------------------");
  90. }
  91. /**
  92. * 处理HTML标签
  93. * @param tag
  94. * @throws Exception
  95. */
  96. public void dealTag(Tag tag) throws Exception {
  97.    NodeList list = tag.getChildren();
  98.    if (list != null) {
  99.     NodeIterator it = list.elements();
  100.     while (it.hasMoreNodes()) {
  101.      Node node = it.nextNode();
  102.      parserNode(node);
  103.     }
  104.    }
  105. }
  106. /**
  107. * 处理HTML标签结点
  108. * @param node
  109. * @throws Exception
  110. */
  111.     public void parserNode(Node node) throws Exception{
  112.     if (node instanceof StringNode) {//判断是否是文本结点
  113.     StringNode sNode = (StringNode) node;
  114.     StringFilter sf = new StringFilter(keyword,false);
  115.     search_key_words = sf.accept(sNode);
  116.     if (search_key_words) {
  117.      count++;
  118.     }
  119.     // System.out.println("text is :"+sNode.getText().trim());
  120.    } else if (node instanceof Tag) {//判断是否是标签库结点
  121.     Tag atag = (Tag) node;
  122.     if (atag instanceof TitleTag) {//判断是否是标TITLE结点
  123.      srb.setTitle(atag.getText());
  124.     }
  125.     if (atag instanceof LinkTag) {//判断是否是标LINK结点
  126.      LinkTag linkatag = (LinkTag) atag;
  127.      checkLink(linkatag.getLink(), linklist);
  128.      // System.out.println("-----------------this is link --------------");
  129.     }
  130.     dealTag(atag);
  131.    } else if (node instanceof RemarkNode) {//判断是否是注释
  132.     // System.out.println("this is remark");
  133.    }
  134.     }
  135.     /*
  136.      * 检查链接是否需要加入列队
  137.      */
  138. public void checkLink(String link, Queue queue) {
  139.    if (link != null && !link.equals("") && link.indexOf("#") == -1) {
  140.     if (!link.startsWith("http://") && !link.startsWith("ftp://")
  141.       && !link.startsWith("www.")) {
  142.      link = "file:///" + link;
  143.     } else if (link.startsWith("www.")) {
  144.      link = "http://" + link;
  145.     }
  146.     if (queue.isEmpty())
  147.      queue.add(link);
  148.     else {
  149.      String link_end_=link.endsWith("/")?link.substring(0,link.lastIndexOf("/")):(link+"/");
  150.      if (!queue.contains(link)&&!queue .contains(link_end_)) {
  151.       queue.add(link);
  152.      }
  153.     }
  154.    }
  155. }
  156. /**
  157. * 检查该链接是否已经被扫描
  158. * @param list
  159. * @param url
  160. * @return
  161. */
  162. public boolean isSearched(List list, String url) {
  163.    String url_end_ = "";
  164.    if (url.endsWith("/")) {
  165.     url_end_ = url.substring(0, url.lastIndexOf("/"));
  166.    } else {
  167.     url_end_ = url + "/";
  168.    }
  169.    if (list.size() > 0) {
  170.     if (list.indexOf(url) != -1 || list.indexOf(url_end_) != -1) {
  171.      return true;
  172.     }
  173.    }
  174.    return false;
  175. }
  176. /**
  177. * 检查URL是否被允许搜索
  178. * @param urlToCheck
  179. * @return
  180. */
  181. private boolean isRobotAllowed(URL urlToCheck) {
  182.    String host = urlToCheck.getHost().toLowerCase();// 获取给出RUL的主机
  183.    // System.out.println("主机="+host);

  184.    // 获取主机不允许搜索的URL缓存
  185.    ArrayList disallowList = disallowListCache.get(host);

  186.    // 如果还没有缓存,下载并缓存。
  187.    if (disallowList == null) {
  188.     disallowList = new ArrayList();
  189.     try {
  190.      URL robotsFileUrl = new URL("http://" + host + "/robots.txt");
  191.      BufferedReader reader = new BufferedReader(
  192.        new InputStreamReader(robotsFileUrl.openStream()));

  193.      // 读robot文件,创建不允许访问的路径列表。
  194.      String line;
  195.      while ((line = reader.readLine()) != null) {
  196.       if (line.indexOf("Disallow:") == 0) {// 是否包含"Disallow:"
  197.        String disallowPath = line.substring("Disallow:"
  198.          .length());// 获取不允许访问路径

  199.        // 检查是否有注释。
  200.        int commentIndex = disallowPath.indexOf("#");
  201.        if (commentIndex != -1) {
  202.         disallowPath = disallowPath.substring(0,
  203.           commentIndex);// 去掉注释
  204.        }

  205.        disallowPath = disallowPath.trim();
  206.        disallowList.add(disallowPath);
  207.       }
  208.      }
  209.      for (Iterator it = disallowList.iterator(); it.hasNext();) {
  210.       System.out.println("Disallow is :" + it.next());
  211.      }
  212.      // 缓存此主机不允许访问的路径。
  213.      disallowListCache.put(host, disallowList);
  214.     } catch (Exception e) {
  215.      return true// web站点根目录下没有robots.txt文件,返回真
  216.     }
  217.    }

  218.    String file = urlToCheck.getFile();
  219.    // System.out.println("文件getFile()="+file);
  220.    for (int i = 0; i < disallowList.size(); i++) {
  221.     String disallow = disallowList.get(i);
  222.     if (file.startsWith(disallow)) {
  223.      return false;
  224.     }
  225.    }

  226.    return true;
  227. }

  228. public static void main(String[] args) {

  229.    Spider ph = new Spider("英超""http://www.microsoft.com");
  230.    try {
  231.     // ph.processHtml();
  232.     Thread search = new Thread(ph);
  233.     search.start();//启动线程
  234.    } catch (Exception ex) {

  235.    }

  236. }
  237. }

  238. --------------------------------------SearchResultBean.java---------------------------------------------------------


  239. public class SearchResultBean {
  240.    String url = "";
  241.    String title = "";
  242.    String keywords = "";
  243.    int count_key_words = 0;
  244. public int getCount_key_words() {
  245. return count_key_words;
  246. }
  247. public void setCount_key_words(int count_key_words) {
  248. this.count_key_words = count_key_words;
  249. }
  250. public String getKeywords() {
  251. return keywords;
  252. }
  253. public void setKeywords(String keywords) {
  254. this.keywords = keywords;
  255. }
  256. public String getTitle() {
  257. return title;
  258. }
  259. public void setTitle(String title) {
  260. this.title = title;
  261. }
  262. public String getUrl() {
  263. return url;
  264. }
  265. public void setUrl(String url) {
  266. this.url = url;
  267. }
  268. }





 import java.io.BufferedReader;

import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class NetBug {
List findUrls = new ArrayList();//所有发现的url
List pendUrls = new ArrayList();//待处理的url
Hashtable deepUrls = new Hashtable();// 存储所有URL深度

String HomePage;//主页
int webDepth = 2;//搜索深度
private String myDomain;

public static void main(String[] args) {
NetBug nb = new NetBug();
nb.HomePage = "http://www.renren.com";
nb.startHmpg();
} public synchronized String getAUrl() {
String tmpAUrl = pendUrls.get(0);// 未处理的url
pendUrls.remove(0);
return tmpAUrl;
}

public String getDomain() {
String reg = "(?<=http\\://[a-zA-Z0-9]{0,100}[.]{0,1})[^.\\s]*?\\.(com|cn|net|org|biz|info|cc|tv)";
Pattern p = Pattern.compile(reg, Pattern.CASE_INSENSITIVE);
Matcher m = p.matcher(HomePage);
boolean blnp = m.find();
if (blnp == true) {
return m.group(0);
}
return null;
}
public void startHmpg(){
this.myDomain = getDomain();

findUrls.add(HomePage);
pendUrls.add(HomePage);
deepUrls.put(HomePage, 1); System.out.println("Start!"); String tmp = getAUrl();
URL url = null;
try {
url = new URL(tmp);
//System.out.println(url.toString());System.exit(0);
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
this.findUrlFromHtml(url);
int i = 0;
for (i = 0; i < 8; i++) {
new Thread(new Processer(this)).start();
}
}
public void findUrlFromHtml(URL url){
// String ptn = "http://([\\w-]+\\.)+[\\w-]+(/[\\w-./?%&=]*)?";
String ptn = "(?<=(href=)[\"]?[\']?)[http://][^\\s\"\'\\?]*("
+ myDomain + ")[^\\s\"\'>]*";
Pattern p = Pattern.compile(ptn, Pattern.CASE_INSENSITIVE);

BufferedReader br = null;
HttpURLConnection conn;
try {
conn = (HttpURLConnection) url.openConnection();

br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line;
while ((line = br.readLine()) != null) {
// System.out.println(line);
Matcher m = p.matcher(line);
if (deepUrls.get(url.toString()) < webDepth){
while (m.find()) {
if(!findUrls.contains(m.group())){
System.out.println(m.group());
findUrls.add(m.group());
pendUrls.add(m.group());
deepUrls.put(m.group(0), (deepUrls.get(url.toString()) + 1));
}
}
}
}

System.out.println("Get web successfully! " + url);

} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
br.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

class Processer implements Runnable {
NetBug nb;
String s;
public Processer(NetBug nb) {
this.nb = nb;
}
public Processer(NetBug nb,String s) {
this.nb = nb;
this.s = s;
} public void run() {
// Thread.sleep(5000);

while (!pendUrls.isEmpty()){
try {
String tmp = getAUrl();
URL url = null;
url = new URL(tmp);
nb.findUrlFromHtml(url);
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

}
}
}
}



百度贴吧的链接都是相对链接。。。懒得搞了。。。
周末有时间搞一下,提取出贴吧各个帖子的邮箱出来。。。
然后再写个程序群发垃圾邮件。。。







教你如何编写简单的网络爬虫

作者: 字体:[增加 减小] 类型:转载 时间:2013-10-12 我要评论
实际的爬虫是从一系列的种子链接开始。种子链接是起始节点,种子页面的超链接指向的页面是子节点(中间节点),对于非html文档,如excel等,不能从中提取超链接,看做图的终端节点

一、网络爬虫的基本知识

网络爬虫通过遍历互联网络,把网络中的相关网页全部抓取过来,这体现了爬的概念。爬虫如何遍历网络呢,互联网可以看做是一张大图,每个页面看做其中的一个节点,页面的连接看做是有向边。图的遍历方式分为宽度遍历和深度遍历,但是深度遍历可能会在深度上过深的遍历或者陷入黑洞。所以,大多数爬虫不采用这种形式。另一方面,爬虫在按照宽度优先遍历的方式时候,会给待遍历的网页赋予一定优先级,这种叫做带偏好的遍历。

实际的爬虫是从一系列的种子链接开始。种子链接是起始节点,种子页面的超链接指向的页面是子节点(中间节点),对于非html文档,如excel等,不能从中提取超链接,看做图的终端节点。整个遍历过程中维护一张visited表,记录哪些节点(链接)已经处理过了,跳过不作处理。

使用宽度优先搜索策略,主要原因有:

a、重要的网页一般离种子比较近,例如我们打开的新闻网站时候,往往是最热门的新闻,随着深入冲浪,网页的重要性越来越低。

b、万维网实际深度最多达17层,但到达某个网页总存在一条很短路径,而宽度优先遍历可以最快的速度找到这个网页

c、宽度优先有利于多爬虫合作抓取。

二、网络爬虫的简单实现

1、定义已访问队列,待访问队列和爬取得URL的哈希表,包括出队列,入队列,判断队列是否空等操作
复制代码 代码如下:

package webspider;
import java.util.HashSet;
import java.util.PriorityQueue;
import java.util.Set;
import java.util.Queue;

public class LinkQueue {
 // 已访问的 url 集合
 private static Set visitedUrl = new HashSet();
 // 待访问的 url 集合
 private static Queue unVisitedUrl = new PriorityQueue();

 // 获得URL队列
 public static Queue getUnVisitedUrl() {
  return unVisitedUrl;
 }

 // 添加到访问过的URL队列中
 public static void addVisitedUrl(String url) {
  visitedUrl.add(url);
 }

 // 移除访问过的URL
 public static void removeVisitedUrl(String url) {
  visitedUrl.remove(url);
 }

 // 未访问的URL出队列
 public static Object unVisitedUrlDeQueue() {
  return unVisitedUrl.poll();
 }

 // 保证每个 url 只被访问一次
 public static void addUnvisitedUrl(String url) {
  if (url != null && !url.trim().equals("") && !visitedUrl.contains(url)
    && !unVisitedUrl.contains(url))
   unVisitedUrl.add(url);
 }

 // 获得已经访问的URL数目
 public static int getVisitedUrlNum() {
  return visitedUrl.size();
 }

 // 判断未访问的URL队列中是否为空
 public static boolean unVisitedUrlsEmpty() {
  return unVisitedUrl.isEmpty();
 }

}

2、定义DownLoadFile类,根据得到的url,爬取网页内容,下载到本地保存。此处需要引用commons-httpclient.jar,commons-codec.jar,commons-logging.jar。
复制代码 代码如下:

package webspider;

import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import org.apache.commons.httpclient.DefaultHttpMethodRetryHandler;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.params.HttpMethodParams;

public class DownLoadFile {
 /**
  * 根据 url 和网页类型生成需要保存的网页的文件名 去除掉 url 中非文件名字符
  */
 public String getFileNameByUrl(String url, String contentType) {
  // remove http://
  url = url.substring(7);
  // text/html类型
  if (contentType.indexOf("html") != -1) {
   url = url.replaceAll("[\\?/:*|<>\"]", "_") + ".html";
   return url;
  }
  // 如application/pdf类型
  else {
   return url.replaceAll("[\\?/:*|<>\"]", "_") + "."
     + contentType.substring(contentType.lastIndexOf("/") + 1);
  }
 }

 /**
  * 保存网页字节数组到本地文件 filePath 为要保存的文件的相对地址
  */
 private void saveToLocal(byte[] data, String filePath) {
  try {
   DataOutputStream out = new DataOutputStream(new FileOutputStream(
     new File(filePath)));
   for (int i = 0; i < data.length; i++)
    out.write(data[i]);
   out.flush();
   out.close();
  } catch (IOException e) {
   e.printStackTrace();
  }
 }

 /* 下载 url 指向的网页 */
 public String downloadFile(String url) {
  String filePath = null;
  /* 1.生成 HttpClinet 对象并设置参数 */
  HttpClient httpClient = new HttpClient();
  // 设置 Http 连接超时 5s
  httpClient.getHttpConnectionManager().getParams()
    .setConnectionTimeout(5000);

  /* 2.生成 GetMethod 对象并设置参数 */
  GetMethod getMethod = new GetMethod(url);
  // 设置 get 请求超时 5s
  getMethod.getParams().setParameter(HttpMethodParams.SO_TIMEOUT, 5000);
  // 设置请求重试处理
  getMethod.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,
    new DefaultHttpMethodRetryHandler());

  /* 3.执行 HTTP GET 请求 */
  try {
   int statusCode = httpClient.executeMethod(getMethod);
   // 判断访问的状态码
   if (statusCode != HttpStatus.SC_OK) {
    System.err.println("Method failed: "
      + getMethod.getStatusLine());
    filePath = null;
   }

   /* 4.处理 HTTP 响应内容 */
   byte[] responseBody = getMethod.getResponseBody();// 读取为字节数组
   // 根据网页 url 生成保存时的文件名
   filePath = "f:\\spider\\"
     + getFileNameByUrl(url,
       getMethod.getResponseHeader("Content-Type")
         .getValue());
   saveToLocal(responseBody, filePath);
  } catch (HttpException e) {
   // 发生致命的异常,可能是协议不对或者返回的内容有问题
   System.out.println("Please check your provided http address!");
   e.printStackTrace();
  } catch (IOException e) {
   // 发生网络异常
   e.printStackTrace();
  } finally {
   // 释放连接
   getMethod.releaseConnection();
  }
  return filePath;
 }
}

3、定义HtmlParserTool类,用来获得网页中的超链接(包括a标签,frame中的src等等),即为了得到子节点的URL。需要引入htmlparser.jar
复制代码 代码如下:

package webspider;

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;

public class HtmlParserTool {
 // 获取一个网站上的链接,filter 用来过滤链接
 public static Set extracLinks(String url, LinkFilter filter) {

  Set links = new HashSet();
  try {
   Parser parser = new Parser(url);
   //parser.setEncoding("utf-8");
   // 过滤 标签的 filter,用来提取 frame 标签里的 src 属性所表示的链接
   NodeFilter frameFilter = new NodeFilter() {
    public boolean accept(Node node) {
     if (node.getText().startsWith("frame src=")) {
      return true;
     } else {
      return false;
     }
    }
   };
   // OrFilter 来设置过滤 标签,和 标签
   OrFilter linkFilter = new OrFilter(new NodeClassFilter(
     LinkTag.class), frameFilter);
   // 得到所有经过过滤的标签
   NodeList list = parser.extractAllNodesThatMatch(linkFilter);
   for (int i = 0; i < list.size(); i++) {
    Node tag = list.elementAt(i);
    if (tag instanceof LinkTag)//
标签
    {
     LinkTag link = (LinkTag) tag;
     String linkUrl = link.getLink();// url
     if (filter.accept(linkUrl))
      links.add(linkUrl);
    } else// 标签
    {
     // 提取 frame 里 src 属性的链接如
     String frame = tag.getText();
     int start = frame.indexOf("src=");
     frame = frame.substring(start);
     int end = frame.indexOf(" ");
     if (end == -1)
      end = frame.indexOf(">");
     String frameUrl = frame.substring(5, end - 1);
     if (filter.accept(frameUrl))
      links.add(frameUrl);
    }
   }
  } catch (ParserException e) {
   e.printStackTrace();
  }
  return links;
 }
}

4、编写测试类MyCrawler,用来测试爬取效果
复制代码 代码如下:

package webspider;

import java.util.Set;

public class MyCrawler {
 /**
  * 使用种子初始化 URL 队列
  *
  * @return
  * @param seeds
  *            种子URL
  */
 private void initCrawlerWithSeeds(String[] seeds) {
  for (int i = 0; i < seeds.length; i++)
   LinkQueue.addUnvisitedUrl(seeds[i]);
 }

 /**
  * 抓取过程
  *
  * @return
  * @param seeds
  */
 public void crawling(String[] seeds) { // 定义过滤器,提取以http://www.lietu.com开头的链接
  LinkFilter filter = new LinkFilter() {
   public boolean accept(String url) {
    if (url.startsWith("http://www.baidu.com"))
     return true;
    else
     return false;
   }
  };
  // 初始化 URL 队列
  initCrawlerWithSeeds(seeds);
  // 循环条件:待抓取的链接不空且抓取的网页不多于1000
  while (!LinkQueue.unVisitedUrlsEmpty()
    && LinkQueue.getVisitedUrlNum() <= 1000) {
   // 队头URL出队列
   String visitUrl = (String) LinkQueue.unVisitedUrlDeQueue();
   if (visitUrl == null)
    continue;
   DownLoadFile downLoader = new DownLoadFile();
   // 下载网页
   downLoader.downloadFile(visitUrl);
   // 该 url 放入到已访问的 URL 中
   LinkQueue.addVisitedUrl(visitUrl);
   // 提取出下载网页中的 URL
   Set links = HtmlParserTool.extracLinks(visitUrl, filter);
   // 新的未访问的 URL 入队
   for (String link : links) {
    LinkQueue.addUnvisitedUrl(link);
   }
  }
 }

 // main 方法入口
 public static void main(String[] args) {
  MyCrawler crawler = new MyCrawler();
  crawler.crawling(new String[] { "http://www.baidu.com" });
 }

}

至此,可以看到f:\spider文件夹下面已经出现了很多html文件,都是关于百度的,以“www.baidu.com”为开头。


你可能感兴趣的:(几个简单网络爬虫的例子--还没验证)