找回密码
 立即注册→加入我们

QQ登录

只需一步,快速开始

搜索
热搜: 下载 VB C 实现 编写
查看: 2769|回复: 1

ReactOS爬虫之再改版

[复制链接]
发表于 2014-3-3 13:37:55 | 显示全部楼层 |阅读模式

欢迎访问技术宅的结界,请注册或者登录吧。

您需要 登录 才可以下载或查看,没有账号?立即注册→加入我们

×
http://www.0xaa55.com/thread-285-1-1.html
上次给大家留了2个问题,现在揭晓
问题1:上面代码是栈实现的,请自己写出队列版代码
堆栈版:
  1. import java.io.File;
  2. import java.io.FileInputStream;
  3. import java.io.FileOutputStream;
  4. import java.io.IOException;
  5. import java.io.InputStream;
  6. import java.io.ObjectInputStream;
  7. import java.io.ObjectOutputStream;
  8. import java.io.Serializable;
  9. import java.net.URL;
  10. import java.net.URLConnection;
  11. import java.util.Stack;

  12. import org.jsoup.Jsoup;
  13. import org.jsoup.nodes.Document;
  14. import org.jsoup.nodes.Element;
  15. import org.jsoup.parser.Tag;
  16. import org.jsoup.select.Elements;

  17. public class ReactOSDownloaderStack
  18. {
  19.     public static String url="http://svn.reactos.org/";
  20.     public static String path="k:/reactos/";
  21.     public static int filethreadnum=0;
  22.      
  23.     public static boolean setinit=false;//是否强制初始化
  24.     public static String[] initstring={};//初始化目录位要开始更新的目录,按深度顺序
  25.     public static int curdepth=0;//当前初始化深度
  26.     public static Stack<FolderClass> folders=new Stack<FolderClass>();

  27.     public static class SerialElement implements Serializable
  28.     {
  29.         /**
  30.          *
  31.          */
  32.         public String attrhref="";
  33.         private static final long serialVersionUID = 1L;
  34.         
  35.         public SerialElement(Element ele)
  36.         {
  37.             attrhref=ele.attr("href");
  38.         }
  39.     }
  40.    
  41.     public static class SerialData implements Serializable
  42.     {
  43.         /**
  44.          *
  45.          */
  46.         public Stack<FolderClass> inner=new Stack<FolderClass>();
  47.         private static final long serialVersionUID = 1L;
  48.         public SerialData(Stack<FolderClass> data)
  49.         {
  50.             inner.clear();
  51.             inner.addAll(data);
  52.         }
  53.         public void ReadFromData(Stack<FolderClass> data)
  54.         {
  55.             data.clear();
  56.             data.addAll(inner);
  57.         }
  58.     }
  59.    
  60.     public static class FileThread extends Thread
  61.     {
  62.         String filepath;
  63.         String curnode;
  64.          
  65.         FileThread(String filepath,String curnode)
  66.         {
  67.             this.filepath=filepath;
  68.             this.curnode=curnode;
  69.         }
  70.         
  71.         @Override
  72.         public void run()
  73.         {
  74.             try
  75.             {
  76.                 while(filethreadnum>30)
  77.                 {
  78.                     sleep(1000);
  79.                 }
  80.                 filethreadnum++;
  81.                 int byteread=0;
  82.                 int bytesum=0;
  83.                 URL weburl=new URL(url+filepath+curnode);
  84.                 URLConnection con=weburl.openConnection();
  85.                 InputStream instream=con.getInputStream();
  86.                 FileOutputStream fs=new FileOutputStream(escape((path+filepath+curnode).replace("%20"," ")));
  87.                 byte[] buffer=new byte[65536];
  88.                 while((byteread=instream.read(buffer)) != -1)
  89.                 {
  90.                     bytesum+=byteread;
  91.                     fs.write(buffer,0,byteread);
  92.                     System.out.println("\t\t当前下载文件:"+filepath+curnode+"\t当前大小:"+bytesum);
  93.                 }
  94.                 fs.close();
  95.                 instream.close();
  96.                 filethreadnum--;
  97.             }
  98.             catch(Exception e)
  99.             {
  100.                 System.out.println("error");
  101.                 filethreadnum--;
  102.                 new File(path+filepath+curnode).deleteOnExit();;
  103.             }
  104.         }
  105.     }
  106.      
  107.     public static String escape(String src)
  108.     {
  109.         StringBuffer sbuf=new StringBuffer();
  110.         int len=src.length();

  111.         for(int i=3;i<len;i++)
  112.         {
  113.             char ch=src.charAt(i);
  114.             if(ch == '\\' || ch == ':' || ch == '*' || ch == '?' || ch == '"' || ch == '<' || ch == '>' || ch == '|')
  115.                 ;
  116.             else
  117.                 sbuf.append(ch);
  118.         }
  119.         return src.substring(0,3)+formatpath(sbuf.toString());
  120.     }
  121.      
  122.     public static String formatpath(String src)
  123.     {
  124.         if(!src.contains("http"))
  125.             return src;
  126.         String newstr=src.substring(0,10)+src.substring(10).replaceAll("/{2,}", "/");
  127.         return newstr;
  128.     }
  129.      
  130.     public static String createFolder(String folderPath)
  131.     {
  132.         String txt = folderPath;
  133.         try
  134.         {
  135.             File myFilePath = new File(txt);
  136.             txt = folderPath;
  137.             if (!myFilePath.exists())
  138.             {
  139.                 myFilePath.mkdir();
  140.         }
  141.     }
  142.     catch (Exception e)
  143.     {
  144.         System.out.println("错误!");
  145.     }
  146.         return txt;
  147.     }

  148.     public static class FolderClass implements Serializable
  149.     {
  150.         String filepath;
  151.         SerialElement e;
  152.         
  153.         public FolderClass(SerialElement e,String filepath)
  154.         {
  155.             this.filepath=filepath;
  156.             this.e=e;
  157.         }
  158.          
  159.         public void ResolveFolder()
  160.         {
  161.             try
  162.             {            
  163.                 String curnode=e.attrhref;
  164.                 if(curnode.indexOf(';') != -1 || curnode.charAt(0) == '/' || curnode.equals("../") || curnode.equals("svn/"))
  165.                     return;
  166.                 System.out.println(curnode+"\t"+filepath);
  167.                 if(setinit)
  168.                 {
  169.                     if(!curnode.equals(initstring[curdepth]))
  170.                         return;
  171.                     else
  172.                         curdepth++;
  173.                     if(curdepth >= initstring.length)
  174.                         setinit=false;
  175.                 }
  176.                   
  177.                 if(curnode.charAt(curnode.length()-1) == '/')
  178.                 {//目录
  179.                     createFolder(escape((path+filepath+curnode).replace("%20"," ")));
  180.                     Document doc=Jsoup.connect(formatpath(url+filepath+curnode)).timeout(0).get();
  181.                     System.out.println("当前目录:"+url+formatpath(filepath)+curnode);
  182.                     Elements items=doc.select("tbody tr a");
  183.                     for(Element ele1:items)
  184.                     {
  185.                         folders.push(new FolderClass(new SerialElement(ele1),filepath+curnode));
  186.                     }
  187.                     items.clear();
  188.                     items=doc.select("ul li a");
  189.                     for(Element ele2:items)
  190.                     {
  191.                         folders.push(new FolderClass(new SerialElement(ele2),filepath+curnode));
  192.                     }
  193.                 }
  194.                 else
  195.                 {//文件
  196.                     File curfile=new File((path+filepath+curnode).replace("%20"," "));
  197.                     if(curfile.exists())
  198.                         return;
  199.                     (new FileThread(filepath,curnode)).start();
  200.                 }
  201.             }
  202.             catch(Exception e)
  203.             {
  204.                 System.out.println("error");
  205.             }
  206.         }
  207.     }
  208.    
  209.     public static void main(String[] args) throws IOException
  210.     {
  211.         try
  212.         {
  213.             if(new File("savedata").exists())
  214.             {
  215.                 FileInputStream fis=new FileInputStream("savedata");
  216.                 ObjectInputStream ois=new ObjectInputStream(fis);
  217.                 SerialData data=(SerialData) ois.readObject();
  218.                 data.ReadFromData(folders);
  219.                 ois.close();
  220.                 fis.close();
  221.             }
  222.             else
  223.             {
  224.                 Document doc = Jsoup.connect(url).timeout(0).get();
  225.                 Elements items=doc.select("tbody tr a");
  226.                 createFolder(path);
  227.                 for(Element e1:items)
  228.                 {
  229.                     folders.push(new FolderClass(new SerialElement(e1),""));
  230.                 }
  231.                 items=doc.select("ul li a");
  232.                 for(Element e2:items)
  233.                 {
  234.                     folders.push(new FolderClass(new SerialElement(e2),""));
  235.                 }
  236.                 new File("savedata").createNewFile();
  237.             }
  238.             
  239.             new Thread()
  240.             {
  241.                 @Override
  242.                 public void run()
  243.                 {
  244.                     while(true)
  245.                     {
  246.                         try
  247.                         {
  248.                             sleep(1000);
  249.                             FileOutputStream fos=new FileOutputStream("savedata");
  250.                             ObjectOutputStream oos=new ObjectOutputStream(fos);
  251.                             SerialData data=new SerialData(folders);
  252.                             oos.writeObject(data);
  253.                             oos.close();
  254.                             fos.close();
  255.                         }
  256.                         catch(Exception e)
  257.                         {
  258.                         }
  259.                     }
  260.                 }
  261.             }.start();
  262.             
  263.             new Thread()
  264.             {
  265.                 @Override
  266.                 public void run()
  267.                 {
  268.                     while(!folders.empty())
  269.                     {
  270.                         int searchonce=30;
  271.                         while(searchonce-- > 0 && !folders.isEmpty())
  272.                         {
  273.                             folders.pop().ResolveFolder();
  274.                         }
  275.                     }
  276.                 }
  277.             }.start();
  278.                
  279.             while(filethreadnum != 0 || folders.size() != 0)
  280.             {
  281.                 Thread.sleep(1000);
  282.             }
  283.         }
  284.         catch(Exception exc)
  285.         {
  286.             System.out.println("错误!"+exc.getMessage());
  287.         }
  288.     }
  289. }
复制代码
队列版:
  1. import java.io.File;
  2. import java.io.FileOutputStream;
  3. import java.io.IOException;
  4. import java.io.InputStream;
  5. import java.net.URL;
  6. import java.net.URLConnection;
  7. import java.util.LinkedList;
  8. import java.util.Queue;
  9. import java.util.Stack;
  10. import org.jsoup.Jsoup;
  11. import org.jsoup.nodes.Document;
  12. import org.jsoup.nodes.Element;
  13. import org.jsoup.select.Elements;
  14. public class ReactOSDownloaderQueue
  15. {
  16.     public static String url="[url=http://svn.reactos.org/]http://svn.reactos.org/[/url]";
  17.     public static String path="k:/reactos/";
  18.     public static int filethreadnum=0;
  19.         
  20.     public static boolean setinit=false;//是否强制初始化
  21.     public static String[] initstring={};//初始化目录位要开始更新的目录,按深度顺序
  22.     public static int curdepth=0;//当前初始化深度
  23.     public static Queue<FolderClass> folders=new LinkedList<FolderClass>();
  24.     public static class FileThread extends Thread
  25.     {
  26.         String filepath;
  27.         String curnode;
  28.                
  29.         FileThread(String filepath,String curnode)
  30.         {
  31.             this.filepath=filepath;
  32.             this.curnode=curnode;
  33.         }
  34.         
  35.         @Override
  36.         public void run()
  37.         {
  38.             try
  39.             {
  40.                 while(filethreadnum>100)
  41.                 {
  42.                     sleep(1000);
  43.                 }
  44.                 filethreadnum++;
  45.                 int byteread=0;
  46.                 int bytesum=0;
  47.                 URL weburl=new URL(url+filepath+curnode);
  48.                 URLConnection con=weburl.openConnection();
  49.                 InputStream instream=con.getInputStream();
  50.                 FileOutputStream fs=new FileOutputStream(escape((path+filepath+curnode).replace("%20"," ")));
  51.                 byte[] buffer=new byte[65536];
  52.                 while((byteread=instream.read(buffer)) != -1)
  53.                 {
  54.                     bytesum+=byteread;
  55.                     fs.write(buffer,0,byteread);
  56.                     System.out.println("\t\t当前下载文件:"+filepath+curnode+"\t当前大小:"+bytesum);
  57.                 }
  58.                 fs.close();
  59.                 instream.close();
  60.                 filethreadnum--;
  61.             }
  62.             catch(Exception e)
  63.             {
  64.                 System.out.println("error");
  65.                 filethreadnum--;
  66.                 new File(path+filepath+curnode).deleteOnExit();;
  67.             }
  68.         }
  69.     }
  70.         
  71.     public static String escape(String src)
  72.     {
  73.         StringBuffer sbuf=new StringBuffer();
  74.         int len=src.length();
  75.         for(int i=3;i<len;i++)
  76.         {
  77.             char ch=src.charAt(i);
  78.             if(ch == '\\' || ch == ':' || ch == '*' || ch == '?' || ch == '"' || ch == '<' || ch == '>' || ch == '|')
  79.                 ;
  80.             else
  81.                 sbuf.append(ch);
  82.         }
  83.         return src.substring(0,3)+formatpath(sbuf.toString());
  84.     }
  85.         
  86.     public static String formatpath(String src)
  87.     {
  88.         if(!src.contains("http"))
  89.             return src;
  90.         String newstr=src.substring(0,10)+src.substring(10).replaceAll("/{2,}", "/");
  91.         return newstr;
  92.     }
  93.         
  94.     public static String createFolder(String folderPath)
  95.     {
  96.         String txt = folderPath;
  97.         try
  98.         {
  99.             File myFilePath = new File(txt);
  100.             txt = folderPath;
  101.             if (!myFilePath.exists())
  102.             {
  103.                 myFilePath.mkdir();
  104.             }
  105.         }
  106.         catch (Exception e)
  107.         {
  108.             System.out.println("错误!");
  109.         }
  110.         return txt;
  111.     }
  112.     public static class FolderClass
  113.     {
  114.         String filepath;
  115.         Element e;
  116.                
  117.         FolderClass(Element e,String filepath)
  118.         {
  119.             this.filepath=filepath;
  120.             this.e=e;
  121.         }
  122.                
  123.         public void ResolveFolder()
  124.         {
  125.             try
  126.             {      
  127.                 String curnode=e.attr("href");
  128.                 if(curnode.indexOf(';') != -1 || curnode.charAt(0) == '/' || curnode.equals("../") || curnode.equals("svn/"))
  129.                     return;
  130.                 System.out.println(curnode+"\t"+filepath);
  131.                 if(setinit)
  132.                 {
  133.                     if(!curnode.equals(initstring[curdepth]))
  134.                         return;
  135.                     else
  136.                         curdepth++;
  137.                     if(curdepth >= initstring.length)
  138.                         setinit=false;
  139.                 }
  140.                         
  141.                 if(curnode.charAt(curnode.length()-1) == '/')
  142.                 {//目录
  143.                     createFolder(escape((path+filepath+curnode).replace("%20"," ")));
  144.                     Document doc=Jsoup.connect(formatpath(url+filepath+curnode)).timeout(0).get();
  145.                     System.out.println("当前目录:"+url+formatpath(filepath)+curnode);
  146.                     Elements items=doc.select("tbody tr a");
  147.                     for(Element ele1:items)
  148.                     {
  149.                         folders.offer(new FolderClass(ele1,filepath+curnode));
  150.                     }
  151.                     items.clear();
  152.                     items=doc.select("ul li a");
  153.                     for(Element ele2:items)
  154.                     {
  155.                         folders.offer(new FolderClass(ele2,filepath+curnode));
  156.                     }
  157.                 }
  158.                 else
  159.                 {//文件
  160.                     File curfile=new File((path+filepath+curnode).replace("%20"," "));
  161.                     if(curfile.exists())
  162.                         return;
  163.                     (new FileThread(filepath,curnode)).start();
  164.                 }
  165.             }
  166.             catch(Exception e)
  167.             {
  168.                 System.out.println("error");
  169.             }
  170.         }
  171.     }
  172.    
  173.     public static void main(String[] args) throws IOException
  174.     {
  175.         try
  176.         {
  177.             Document doc = Jsoup.connect(url).timeout(0).get();
  178.             Elements items=doc.select("tbody tr a");
  179.             createFolder(path);
  180.             for(Element e1:items)
  181.             {
  182.                 folders.offer(new FolderClass(e1,""));
  183.             }
  184.             items=doc.select("ul li a");
  185.             for(Element e2:items)
  186.             {
  187.                 folders.offer(new FolderClass(e2,""));
  188.             }
  189.             
  190.             new Thread()
  191.             {
  192.                 @Override
  193.                 public void run()
  194.                 {
  195.                     while(!folders.isEmpty())
  196.                     {
  197.                         int searchonce=(folders.size()>100)?100:folders.size();
  198.                         while(searchonce-- > 0)
  199.                         {
  200.                             folders.poll().ResolveFolder();
  201.                         }
  202.                     }
  203.                 }
  204.             }.start();
  205.                         
  206.             while(filethreadnum != 0)
  207.             {
  208.                 Thread.sleep(1000);
  209.             }
  210.         }
  211.         catch(Exception exc)
  212.         {
  213.             System.out.println("错误!");
  214.         }
  215.     }
  216. }
复制代码
问题2:代码中实现了一种功能,它允许你今天下载了一部分reactos代码,然后结束java程序,第二天开电脑的时候只需要设置以下参数,就可以从昨天开始处继续运行,请问代码中如何实现的
在最早的版本(非队列非堆栈版)里,这种继续下载的机制是通过记录目录实现的
关键代码在:
  1. public static boolean setinit=false;//是否强制初始化
  2. 。。。。。
  3.     if(setinit)
  4.     {
  5.             if(!curnode.equals(initstring[curdepth]))
  6.                 return;
  7.             else
  8.                 curdepth++;
  9.             if(curdepth >= initstring.length)
  10.                 setinit=false;
  11.     }
复制代码



而在上面的堆栈版,是通过java独有的序列化方式实现的,,每隔1秒将堆栈数据写入文件,启动时读出。序列化和反射是java最强大的2各功能,其中序列化可以保存任何东西,包括类
关键代码在:
  1. public static class SerialElement implements Serializable
  2. {
  3.     /**
  4.         *
  5.         */
  6.     public String attrhref="";
  7.     private static final long serialVersionUID = 1L;
  8.    
  9.     public SerialElement(Element ele)
  10.     {
  11.         attrhref=ele.attr("href");
  12.     }
  13. }

  14. public static class SerialData implements Serializable
  15. {
  16.     /**
  17.         *
  18.         */
  19.     public Stack<FolderClass> inner=new Stack<FolderClass>();
  20.     private static final long serialVersionUID = 1L;
  21.     public SerialData(Stack<FolderClass> data)
  22.     {
  23.         inner.clear();
  24.         inner.addAll(data);
  25.     }
  26.     public void ReadFromData(Stack<FolderClass> data)
  27.     {
  28.         data.clear();
  29.         data.addAll(inner);
  30.     }
  31. }
  32. 。。。
  33.         if(new File("savedata").exists())
  34.         {
  35.             FileInputStream fis=new FileInputStream("savedata");
  36.             ObjectInputStream ois=new ObjectInputStream(fis);
  37.             SerialData data=(SerialData) ois.readObject();
  38.             data.ReadFromData(folders);
  39.             ois.close();
  40.             fis.close();
  41.         }
  42. 。。。
  43.         new Thread()
  44.         {
  45.             @Override
  46.             public void run()
  47.             {
  48.                 while(true)
  49.                 {
  50.                     try
  51.                     {
  52.                      sleep(1000);
  53.                      FileOutputStream fos=new FileOutputStream("savedata");
  54.                      ObjectOutputStream oos=new ObjectOutputStream(fos);
  55.                      SerialData data=new SerialData(folders);
  56.                      oos.writeObject(data);
  57.                      oos.close();
  58.                      fos.close();
  59.                     }
  60.                     catch(Exception e)
  61.                     {
  62.                     }
  63.                 }
  64.             }
  65.         }.start();
复制代码


经测试,性能没有较大改变,且输出的文件总在7k以内,说明堆栈项目最多在200,很少

这次给你们留的问题so-easy,
①我只实现了堆栈版的序列化,现在你们实现队列版的序列化

②对比堆栈版和队列版运行速度,并说明原因

回复

使用道具 举报

发表于 2014-3-24 01:00:02 | 显示全部楼层
不明觉厉~~mark
回复 赞! 靠!

使用道具 举报

本版积分规则

QQ|Archiver|小黑屋|技术宅的结界 ( 滇ICP备16008837号 )|网站地图

GMT+8, 2024-12-23 06:44 , Processed in 0.030260 second(s), 20 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表