Spider.cs
上传用户:yxdanqu
上传日期:2010-01-07
资源大小:84k
文件大小:6k
源码类别:

搜索引擎

开发平台:

C#

  1. using System;
  2. using System.Collections;
  3. using System.Net;
  4. using System.IO;
  5. using System.Threading;
  6. namespace Spider
  7. {
  8. /// <summary>
  9. /// The main class for the spider. This spider can be used with the 
  10. /// SpiderForm form that has been provided. The spider is completely 
  11. /// selfcontained. If you would like to use the spider with your own
  12. /// application just remove the references to m_spiderForm from this file.
  13. /// 
  14. /// The files needed for the spider are:
  15. /// 
  16. /// Attribute.cs - Used by the HTML parser
  17. /// AttributeList.cs - Used by the HTML parser
  18. /// DocumentWorker - Used to "thread" the spider
  19. /// Done.cs - Allows the spider to know when it is done
  20. /// Parse.cs - Used by the HTML parser
  21. /// ParseHTML.cs - The HTML parser
  22. /// Spider.cs - This file
  23. /// SpiderForm.cs - Demo of how to use the spider
  24. /// 
  25. /// This spider is copyright 2003 by Jeff Heaton. However, it is
  26. /// released under a Limited GNU Public License (LGPL). You may 
  27. /// use it freely in your own programs. For the latest version visit
  28. /// http://www.jeffheaton.com.
  29. ///
  30. /// </summary>
  31. public class Spider
  32. {
  33. /// <summary>
  34. /// The URL's that have already been processed.
  35. /// </summary>
  36. private Hashtable m_already;
  37. /// <summary>
  38. /// URL's that are waiting to be processed.
  39. /// </summary>
  40. private Queue m_workload;
  41. /// <summary>
  42. /// The first URL to spider. All other URL's must have the
  43. /// same hostname as this URL. 
  44. /// </summary>
  45. private Uri m_base;
  46. /// <summary>
  47. /// The directory to save the spider output to.
  48. /// </summary>
  49. private string m_outputPath;
  50. /// <summary>
  51. /// The form that the spider will report its 
  52. /// progress to.
  53. /// </summary>
  54. private SpiderForm m_spiderForm;
  55. /// <summary>
  56. /// How many URL's has the spider processed.
  57. /// </summary>
  58. private int m_urlCount = 0;
  59. /// <summary>
  60. /// When did the spider start working
  61. /// </summary>
  62. private long m_startTime = 0;
  63. /// <summary>
  64. /// Used to keep track of when the spider might be done.
  65. /// </summary>
  66. private Done m_done = new Done();
  67. /// <summary>
  68. /// Used to tell the spider to quit.
  69. /// </summary>
  70. private bool m_quit;
  71. /// <summary>
  72. /// The status for each URL that was processed.
  73. /// </summary>
  74. enum Status { STATUS_FAILED, STATUS_SUCCESS, STATUS_QUEUED };
  75. /// <summary>
  76. /// The constructor
  77. /// </summary>
  78. public Spider()
  79. {
  80. reset();
  81. }
  82. /// <summary>
  83. /// Call to reset from a previous run of the spider
  84. /// </summary>
  85. public void reset()
  86. {
  87. m_already = new Hashtable();
  88. m_workload = new Queue();
  89. m_quit = false;
  90. }
  91. /// <summary>
  92. /// Add the specified URL to the list of URI's to spider.
  93. /// This is usually only used by the spider, itself, as
  94. /// new URL's are found.
  95. /// </summary>
  96. /// <param name="uri">The URI to add</param>
  97. public void addURI(Uri uri)
  98. {
  99. Monitor.Enter(this);
  100. if( !m_already.Contains(uri) )
  101. {
  102. m_already.Add(uri,Status.STATUS_QUEUED);
  103. m_workload.Enqueue(uri);
  104. }
  105. Monitor.Pulse(this);
  106. Monitor.Exit(this);
  107. }
  108. /// <summary>
  109. /// The URI that is to be spidered
  110. /// </summary>
  111. public Uri BaseURI 
  112. {
  113. get
  114. {
  115. return m_base;
  116. }
  117. set
  118. {
  119. m_base = value;
  120. }
  121. }
  122. /// <summary>
  123. /// The local directory to save the spidered files to
  124. /// </summary>
  125. public string OutputPath
  126. {
  127. get
  128. {
  129. return m_outputPath;
  130. }
  131. set
  132. {
  133. m_outputPath = value;
  134. }
  135. }
  136. /// <summary>
  137. /// The object that the spider reports its
  138. /// results to.
  139. /// </summary>
  140. public SpiderForm ReportTo
  141. {
  142. get
  143. {
  144. return m_spiderForm;
  145. }
  146. set
  147. {
  148. m_spiderForm = value;
  149. }
  150. }
  151. /// <summary>
  152. /// Set to true to request the spider to quit.
  153. /// </summary>
  154. public bool Quit
  155. {
  156. get
  157. {
  158. return m_quit;
  159. }
  160. set
  161. {
  162. m_quit = value;
  163. }
  164. }
  165. /// <summary>
  166. /// Used to determine if the spider is done, 
  167. /// this object is usually only used internally
  168. /// by the spider.
  169. /// </summary>
  170. public Done SpiderDone
  171. {
  172. get
  173. {
  174. return m_done;
  175. }
  176. }
  177. /// <summary>
  178. /// Called by the worker threads to obtain a URL to
  179. /// to process.
  180. /// </summary>
  181. /// <returns>The next URL to process.</returns>
  182. public Uri ObtainWork()
  183. {
  184. Monitor.Enter(this);
  185. while(m_workload.Count<1)
  186. {
  187. Monitor.Wait(this);
  188. }
  189. Uri next = (Uri)m_workload.Dequeue();
  190. if(m_spiderForm!=null)
  191. {
  192. m_spiderForm.SetLastURL(next.ToString());
  193. m_spiderForm.SetProcessedCount(""+(m_urlCount++));
  194. long etime = (System.DateTime.Now.Ticks-m_startTime)/10000000L;
  195. long urls = (etime==0)?0:m_urlCount/etime;
  196. m_spiderForm.SetElapsedTime( etime/60 + " minutes (" + urls +" urls/sec)" );
  197. }
  198. Monitor.Exit(this);
  199. return next;
  200. }
  201. /// <summary>
  202. /// Start the spider.
  203. /// </summary>
  204. /// <param name="baseURI">The base URI to spider</param>
  205. /// <param name="threads">The number of threads to use</param>
  206. public void Start(Uri baseURI,int threads)
  207. {
  208. // init the spider
  209. m_quit = false;
  210. m_base = baseURI;
  211. addURI(m_base);
  212. m_startTime = System.DateTime.Now.Ticks;;
  213. m_done.Reset();
  214. // startup the threads
  215. for(int i=1;i<threads;i++)
  216. {
  217. DocumentWorker worker = new DocumentWorker(this);
  218. worker.Number = i;
  219. worker.start();
  220. }
  221. // now wait to be done
  222. m_done.WaitBegin();
  223. m_done.WaitDone();
  224. }
  225. }
  226. }