编程语言

img caoxu1987728

抓取网页GetSite

发表于2008/10/1 15:55:00  999人阅读

 大略扫描了一下整本书,感觉上写spider最符合我现在的学习要求,那就专心看编写Spider程序了。

程序是可以运行,但是却没有得到实际的东西,for example:href=“content.asp?id=2565”,尽管知道它是internal链接,可是spider却不抓取。总之,从下列代码清单中,本人还无法找到确切的原因而修改之;

效果如下:

 

 

代码清单如下:

  1. import java.awt.Dimension;
  2. import java.awt.Insets;
  3. import java.io.File;
  4. import java.io.FileOutputStream;
  5. import java.net.URL;
  6. import javax.swing.JOptionPane;
  7. import javax.swing.SwingUtilities;
  8. import com.heaton.bot.HTTP;
  9. import com.heaton.bot.HTTPSocket;
  10. import com.heaton.bot.ISpiderReportable;
  11. import com.heaton.bot.IWorkloadStorable;
  12. import com.heaton.bot.Log;
  13. import com.heaton.bot.Spider;
  14. import com.heaton.bot.SpiderInternalWorkload;
  15. import com.heaton.bot.URLUtility;
  16. /** *
  17.  * This example program will download all of the HTML files
  18.  * of a website to a local drive. This shows how a spider can
  19.  * be used to map/download a site.
  20.  */
  21. public class GetSite extends javax.swing.JFrame implements ISpiderReportable {
  22.   /**
  23.    * The underlying spider object. 
  24.    * 基本的爬虫对象。           
  25.    */
  26.   Spider _spider = null;
  27.   /**
  28.    * The current page count.
  29.    */
  30.   int _pagesCount;
  31.   /**
  32.    * The constructor. Set up the visual(可视化的) Swing
  33.    * components that make up the user interface
  34.    * for this program.
  35.    */
  36.   public GetSite()
  37.   {
  38.     /*
  39.      * 初始化控制界面
  40.      */
  41.     setTitle("Download Site");
  42.     getContentPane().setLayout(null);
  43.     setSize(405,268);
  44.     setVisible(false);
  45.     
  46.     D.setHorizontalTextPosition(
  47.                                javax.swing.SwingConstants.LEFT);
  48.     D.setVerticalTextPosition(
  49.                              javax.swing.SwingConstants.TOP);
  50.     D.setVerticalAlignment(
  51.                           javax.swing.SwingConstants.TOP);
  52.     D.setText("Download pages of:");
  53.     getContentPane().add(D);
  54.     D.setBounds(12,12,384,24);
  55.     
  56.     JLabel2.setText("URL:");
  57.     getContentPane().add(JLabel2);
  58.     JLabel2.setBounds(12,36,36,24);
  59.     
  60.     getContentPane().add(_url);
  61.     _url.setBounds(48,36,348,24);
  62.     
  63.     JLabel3.setText("Select local path to download files");
  64.     getContentPane().add(JLabel3);
  65.     JLabel3.setBounds(12,72,384,24);
  66.     
  67.     getContentPane().add(_save);
  68.     _save.setBounds(12,96,384,24);
  69.     
  70.     _go.setText("GO!");
  71.     getContentPane().add(_go);
  72.     _go.setBounds(96,228,216,24);
  73.     
  74.     /*
  75.      * _current表示当前spider抓取的网页名称,显示在这里
  76.      * go的上方(即可以作为状态使用)。
  77.      */
  78.     getContentPane().add(_current);
  79.     _current.setBounds(12,204,384,12);
  80.    
  81.     
  82.     JLabel4.setText("Number of pages:");
  83.     getContentPane().add(JLabel4);
  84.     JLabel4.setBounds(12,180,120,12);
  85.     
  86.     _pages.setText("0");
  87.     getContentPane().add(_pages);
  88.     _pages.setBounds(120,180,108,12);
  89.     
  90.     JLabel6.setText(
  91.      "Select local path(and filename) to write log to(optional):");
  92.     getContentPane().add(JLabel6);
  93.     JLabel6.setBounds(12,120,384,24);
  94.     
  95.     _logPath.setText("./spider.log");
  96.     getContentPane().add(_logPath);
  97.     _logPath.setBounds(12,144,384,24);
  98.     
  99.     _go.setActionCommand("jbutton");
  100.   
  101.     SymAction lSymAction = new SymAction();
  102.     _go.addActionListener(lSymAction);
  103.     
  104.     SymWindow aSymWindow = new SymWindow();
  105.     this.addWindowListener(aSymWindow);
  106.     setLocation(32,32);
  107.   }
  108.   public void setVisible(boolean b)
  109.   {
  110.     if ( b )
  111.       setLocation(5050);
  112.     super.setVisible(b);
  113.   }
  114.   /**
  115.    * Program entry point, causes the main
  116.    */
  117.   static public void main(String args[])
  118.   {
  119.     (new GetSite()).setVisible(true);
  120.   }
  121. /*
  122.    Makes this Frame displayable(显示) by connecting it to
  123.     a native screen resource. Making a frame displayable 
  124.     will cause any of its children to be made displayable. 
  125.     This method is called(调用) internally by the toolkit and 
  126.     should not be called directly by programs. 
  127.  */
  128.   public void addNotify()
  129.   {
  130.     /*
  131.      * Record the size of the window prior to calling parents addNotify.
  132.      * 记录窗口之前,通知父类增加通知
  133.      */
  134.     
  135.     Dimension size = getSize();
  136.     super.addNotify();
  137.     if ( frameSizeAdjusted )
  138.       return;
  139.     frameSizeAdjusted = true;
  140.     // Adjust(调整) size of frame according to the insets(镶) and menu bar
  141.     Insets insets = getInsets();
  142.     /*
  143.      * An Insets object is a representation of the borders of a container.
  144.      *  It specifies (指定)the space that a container must leave at each of its edges. 
  145.      *  The space can be a border, a blank space, or a title. 
  146.      */
  147.     javax.swing.JMenuBar menuBar = getRootPane().getJMenuBar();
  148.     int menuBarHeight = 0;
  149.     if ( menuBar != null )
  150.       menuBarHeight = menuBar.getPreferredSize().height;
  151.     setSize(insets.left +
  152.             insets.right +
  153.             size.width,
  154.             insets.top +
  155.             insets.bottom +
  156.             size.height + menuBarHeight);
  157.   }
  158.   boolean frameSizeAdjusted = false;
  159.   javax.swing.JLabel D = new javax.swing.JLabel();
  160.   javax.swing.JLabel JLabel2 = new javax.swing.JLabel();
  161.   /**
  162.    * The URL to spider.
  163.    */
  164.   javax.swing.JTextField _url = new javax.swing.JTextField();
  165.   javax.swing.JLabel JLabel3 = new javax.swing.JLabel();
  166.   /**
  167.    * The directory to save the files to.
  168.    */
  169.   javax.swing.JTextField _save = new javax.swing.JTextField();
  170.   /**
  171.    * The go button.
  172.    */
  173.   javax.swing.JButton _go = new javax.swing.JButton();
  174.   /**
  175.    * Displays(显示) the current page.
  176.    */
  177.   javax.swing.JLabel _current = new javax.swing.JLabel();
  178.   javax.swing.JLabel JLabel4 = new javax.swing.JLabel();
  179.   /**
  180.    * A count of how many pages have been
  181.    * downloaded.
  182.    */
  183.   javax.swing.JLabel _pages = new javax.swing.JLabel();
  184.   javax.swing.JLabel JLabel6 = new javax.swing.JLabel();
  185.   /**
  186.    * Used to specify(指定) the path to store the
  187.    * log to.
  188.    */
  189.   javax.swing.JTextField _logPath = new javax.swing.JTextField();
  190.   /**
  191.    * An event handler class.
  192.    */
  193.   class SymAction implements java.awt.event.ActionListener {
  194.     public void actionPerformed(java.awt.event.ActionEvent event)
  195.     {
  196.       Object object = event.getSource();
  197.       if ( object == _go )
  198.         Go_actionPerformed(event);
  199.     }
  200.   }
  201.   /**
  202.    * As the files of the website are located,
  203.    * this method is called to save them to disk.
  204.    * 
  205.    * file The HTTP object corrisponding(对应) to the page
  206.    * just visited.
  207.    */
  208.   protected void processFile(HTTP file)
  209.   {
  210.     try {
  211.       //System.out.println(file.getURL());
  212.       if ( _save.getText().length()>0 ) {
  213.         URL url = new URL(file.getURL());
  214.         String targetPath = url.getPath();
  215.         
  216.         
  217.         // 这个可能就是把targetPath加入到_save目录下面
  218.          
  219.         
  220.         targetPath = URLUtility.convertFilename(_save.getText(),targetPath);
  221.         FileOutputStream fso =
  222.               new FileOutputStream(
  223.               new File(targetPath) );
  224.         fso.write( file.getBodyBytes() );
  225.         fso.close();
  226.         
  227.        }
  228.     } catch ( Exception e ) {
  229.       Log.logException("Can't save output file: ",e);
  230.     }
  231.       /*
  232.       try {
  233.           if ( _save.getText().length()>0 ) {
  234.             int i = file.getURL().lastIndexOf('/');
  235.             if ( i!=-1 ) {
  236.               String filename = file.getURL().substring(i);
  237.               if ( filename.equals("/") )
  238.                 filename="root.html";
  239.               FileOutputStream fso
  240.               = new FileOutputStream(
  241.                                     new File(_save.getText(),filename) );
  242.               fso.write( file.getBody().getBytes("8859_1") );
  243.               fso.close();
  244.             }
  245.           }
  246.         } catch ( Exception e ) {
  247.           Log.logException("Can't save output file: ",e);
  248.         }   
  249.         */    
  250.  }
  251.   /**
  252.    * This is where most of the action takes place. This
  253.    * method is called when the GO! button is pressed.
  254.    *
  255.    */
  256.   void Go_actionPerformed(java.awt.event.ActionEvent event)
  257.   {
  258.     /*
  259.      * 创建作业管理器的对象w1,本例SpiderInternalWorkload()
  260.      * 为内存管理。
  261.      */
  262.     IWorkloadStorable wl = new SpiderInternalWorkload();
  263.     if ( _spider!=null ) {
  264.       /*
  265.        * The Runnable interface should be implemented by any class 
  266.        * whose instances are intended to be executed(执行) by a thread. 
  267.        * The class must define a method of no arguments called run.
  268.          
  269.          This interface is designed to provide a common protocol for 
  270.          objects that wish to execute code while they are active. 
  271.          For example, Runnable is implemented by class Thread. Being 
  272.          active simply means that a thread has been started and has not yet been stopped. 
  273.          
  274.         In addition, Runnable provides the means for a class to be active 
  275.         while not subclassing Thread. A class that implements Runnable can 
  276.         run without subclassing Thread by instantiating(实例化) a Thread instance 
  277.         and passing itself in as the target. In most cases, the Runnable interface 
  278.         should be used if you are only planning to override the run() method and 
  279.         no other Thread methods. This is important because classes should not 
  280.         be subclassed unless the programmer intends on modifying or enhancing(增强、提高) 
  281.         the fundamental behavior of the class. 
  282.        */
  283.       Runnable doLater = new Runnable()
  284.       {
  285.         public void run()
  286.         {
  287.           _go.setText("Canceling...");
  288.         }
  289.       };
  290.       /*
  291.        * This will happen after all pending AWT events have been processed. 
  292.        * This method should be used when an application thread needs 
  293.        * to update the GUI.
  294.        */
  295.       SwingUtilities.invokeLater(doLater);
  296.       /*
  297.        * 爬虫终止。
  298.        */
  299.       _spider.halt();
  300.       return;
  301.     }
  302.     try {
  303.       if ( _url.getText().length()>0 ) {
  304.         HTTPSocket http = new HTTPSocket();
  305.         http.send(_url.getText(),null);
  306.       } else {
  307.         _current.setText("<<distributed mode>>");
  308.       }
  309.     } catch ( Exception e ) {
  310.       JOptionPane.showMessageDialog(this,
  311.               e,
  312.               "Error",
  313.               JOptionPane.OK_CANCEL_OPTION,
  314.               null );
  315.       return;
  316.     }
  317.     Runnable doLater = new Runnable()
  318.     {
  319.       public void run()
  320.       {
  321.         _go.setText("Cancel");
  322.         _current.setText("Loading....");
  323.       }
  324.     };
  325.     SwingUtilities.invokeLater(doLater);
  326.     // Prepare to start the spider
  327.     _pagesCount = 0;
  328.     
  329.     if ( _logPath.getText().length()>0 ) {
  330.       File file = new File(_logPath.getText());
  331.       file.delete();
  332.       Log.setLevel(Log.LOG_LEVEL_NORMAL);
  333.       Log.setFile(true);
  334.       Log.setConsole(false);
  335.       Log.setPath(_logPath.getText());
  336.     }
  337.     _spider
  338.     = new Spider( this,
  339.                   _url.getText(),
  340.                   new HTTPSocket(),
  341.                   100,
  342.                   wl);
  343.     /*
  344.      * w1为SpiderInternalWorkload()的实例。
  345.      */
  346.     _spider.setMaxBody(200);
  347.     _spider.start();
  348.   }
  349.   /**
  350.    * This method is called by the spider when an
  351.    * internal link is found.
  352.    */
  353.   public boolean foundInternalLink(String url)
  354.   {
  355.     return true;
  356.   }
  357.   /**
  358.    * This method is called by the spider when an
  359.    * external link is found. An external link is
  360.    * one that points to a different host.
  361.    */
  362.   public boolean foundExternalLink(String url)
  363.   {
  364.     return false;
  365.   }
  366.   /**
  367.    * This method is called by the spider when an
  368.    * other type link is found. Links such as email
  369.    * addresses are sent to this method.
  370.    */
  371.   public boolean foundOtherLink(String url)
  372.   {
  373.     return true;
  374.   }
  375.   /**
  376.    * A simple class used to update the current
  377.    * URL target. This is necessary, because Swing
  378.    * only allows GUI compoents to be updated by the
  379.    * main thread.
  380.    * 内部类
  381.    */
  382.   class UpdateTarget implements Runnable 
  383.   {
  384.     public String _t;
  385.     public void run()
  386.     {
  387.       _current.setText(_t);
  388.       _pages.setText( "" + _pagesCount );
  389.     }
  390.   }
  391.   /**
  392.    * Called by the spider when a page has been
  393.    * loaded, and should be processed. For the
  394.    * example, this method will save this file
  395.    * to disk.
  396.    */
  397.   public void processPage(HTTP page)
  398.   {
  399.     _pagesCount++;
  400.     UpdateTarget ut = new UpdateTarget();
  401.     ut._t = page.getURL();
  402.     SwingUtilities.invokeLater(ut);
  403.     
  404.     //System.out.println(_pagesCount);
  405.     System.out.println(page);
  406.     processFile(page);
  407.   }
  408.   /**
  409.    * Not used. This must be implemented because
  410.    * of the interface. Called when a page completes.
  411.    */
  412.   public void completePage(HTTP page,boolean error)
  413.   {
  414.   }
  415.   /**
  416.    * This method is called to determine if
  417.    * query strings should be stripped(剥夺,删除).
  418.    */
  419.   public boolean getRemoveQuery()
  420.   {
  421.     return false;
  422.   }
  423.   /**
  424.    * This method is called once the spider
  425.    * has no more work to do.
  426.    */
  427.   public void spiderComplete()
  428.   {
  429.     if ( _spider.isHalted() ) {
  430.       JOptionPane.showMessageDialog(this,
  431.         "Download of site has been canceled. " +
  432.         "Check log file for any errors.",
  433.         "Done",
  434.         JOptionPane.OK_CANCEL_OPTION,
  435.         null );
  436.     } else {
  437.       JOptionPane.showMessageDialog(this,
  438.         "Download of site is complete. " +
  439.         "Check log file for any errors.",
  440.         "Done",
  441.         JOptionPane.OK_CANCEL_OPTION,
  442.         null );
  443.     }
  444.     _spider=null;
  445.     Runnable doLater = new Runnable()
  446.     {
  447.       public void run()
  448.       {
  449.         _go.setText("GO!!");
  450.       }
  451.     };
  452.     SwingUtilities.invokeLater(doLater);
  453.   }
  454.   class SymWindow extends java.awt.event.WindowAdapter 
  455.   {
  456.     public void windowClosed(java.awt.event.WindowEvent event)
  457.     {
  458.       Object object = event.getSource();
  459.       if ( object == GetSite.this )  /*窗口侦听器*/
  460.         GetSite_windowClosed(event);
  461.     }
  462.   }
  463.   void GetSite_windowClosed(java.awt.event.WindowEvent event)
  464.   {
  465.     System.exit(0);
  466.   }
  467. }

以上述代码为例,我修改了好几处,比如修改了processFile这个方法,本以为可能是输入输出流的原因。通过调试,发现应该不会是这个原因,因为在processPage()这个方法里面,“content.asp?id=2565”根本就没有抓到。后来看了一下ISpiderReportable这个接口(下一节细讲)里面的removeQuery方法,好像与本问题有点关联,可把return true改为return false还是不行。两个字,郁闷!

 

阅读全文
0 0

相关文章推荐

img
取 消
img