夏雷

积极人生,努力加油!
获取网页源代码

一个小需求,获取远程页面的源码,主要用于抓数据。原来用的好好的,最近突然不能获取页面源码了,但是仍然可以用浏览器正常浏览。(文后附源码下载。^_^)

  经过分析,原来用的代码如下:

  1. StreamReader sreader  =   null ;   
  2.              string  result  =   string .Empty;   
  3.              try  
  4.              {   
  5.                 HttpWebRequest httpWebRequest  =  (HttpWebRequest)WebRequest.Create(Url);   
  6.                  // httpWebRequest.Timeout = 20;   
  7.                 httpWebRequest.KeepAlive  =   false ;  
  8.                  #endregion   
  9.                 HttpWebResponse httpWebResponse  =  (HttpWebResponse)httpWebRequest.GetResponse();   
  10.                  if  (httpWebResponse.StatusCode  ==  HttpStatusCode.OK)   
  11.                  {   
  12.                     sreader  =   new  StreamReader(httpWebResponse.GetResponseStream(), encoding);   
  13.                     result  =  reader.ReadToEnd();   
  14.                     if  ( null   !=  httpWebResponse)  { httpWebResponse.Close(); }   
  15.                  return  result;    
  16.                 }   
  17.                  return  result; ;   
  18.             }   
  19.              catch  (WebException e)   {    return   null ;  }   
  20.              finally   {  if  (sreader  !=   null )  { sreader.Close(); }  }   


查了下资料,原来需要加参数。

  1.  #region 关键参数,否则会取不到内容 Important Parameters,else get nothing.   
  2.                 httpWebRequest.UserAgent = "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.0.3705;)";   
  3.                 httpWebRequest.Accept = "*/*";   
  4.                 httpWebRequest.KeepAlive = true;   
  5.                 httpWebRequest.Headers.Add("Accept-Language""zh-cn,en-us;q=0.5");  
  6.                 #endregion  



修正后的代码如下:

  1. #region  读取页面详细信息   
  2.          /**/ ///   <summary>    ///  读取页面详细信息    
  3.          ///   </summary>      
  4.          /// <param name="Url"> 需要读取的地址 </param>     
  5.          ///   <param name="encoding"> 读取的编码方式 </param>      
  6.          ///   <returns></returns>      
  7.          public   static   string  GetStringByUrl( string  Url, System.Text.Encoding encoding)   
  8.          {   
  9.              if  (Url.Equals( " about:blank " ))  return   null ; ;   
  10.              if  ( ! Url.StartsWith( " http:// " )  &&   ! Url.StartsWith( " https:// " ))  { Url  =   " http:// "   +  Url; }   
  11.              int  dialCount  =   0 ;   
  12.         loop:   
  13.             StreamReader sreader  =   null ;   
  14.              string  result  =   string .Empty;   
  15.              try  
  16.              {   
  17.                 HttpWebRequest httpWebRequest  =  (HttpWebRequest)WebRequest.Create(Url);   
  18.                  // httpWebRequest.Timeout = 20;   
  19.                  关键参数,否则会取不到内容 Important Parameters,else get nothing. #region  关键参数,否则会取不到内容 Important Parameters,else get nothing.   
  20.                 httpWebRequest.UserAgent  =   " User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.0.3705;) " ;   
  21.                 httpWebRequest.Accept  =   " */* " ;   
  22.                 httpWebRequest.KeepAlive  =   true ;   
  23.                 httpWebRequest.Headers.Add( " Accept-Language " ,  " zh-cn,en-us;q=0.5 " );  
  24.                  #endregion   
  25.                 HttpWebResponse httpWebResponse  =  (HttpWebResponse)httpWebRequest.GetResponse();   
  26.                  if  (httpWebResponse.StatusCode  ==  HttpStatusCode.OK)   
  27.                  {   
  28.                     sreader  =   new  StreamReader(httpWebResponse.GetResponseStream(), encoding);   
  29.                      char [] cCont  =   new   char [ 256 ];   
  30.                      int  count  =  sreader.Read(cCont,  0 ,  256 );   
  31.                      while  (count  >   0 )   
  32.                      {  //  Dumps the 256 characters on a string and displays the string to the console.    
  33.                         String str  =   new  String(cCont,  0 , count);   
  34.                         result  +=  str;   
  35.                         count  =  sreader.Read(cCont,  0 ,  256 );   
  36.                     }   
  37.                 }   
  38.                  if  ( null   !=  httpWebResponse)  { httpWebResponse.Close(); }   
  39.                  return  result;    
  40.             }   
  41.              catch  (WebException e)   
  42.              {   
  43.                  if  (e.Status  ==  WebExceptionStatus.ConnectFailure)  { dialCount ++ ; ReDial(); }   
  44.                  if  (dialCount  <   5 )  {  goto  loop; }   
  45.                  return   null ;   
  46.             }   
  47.              finally   {  if  (sreader  !=   null )  { sreader.Close(); }  }   
  48.         }  
  49.          #endregion   
  50.          public   static   void  ReDial()   
  51.          {   
  52.              int  res  =   1 ;   
  53.              /**/ /// /while (res != 0)   
  54.              /// /{   
  55.              /// /    CSDNWebTest.RASDisplay ras = new RASDisplay();   
  56.              /// /    ras.Disconnect();   
  57.              /// /    res = ras.Connect("asdl");   
  58.              /// /    System.Threading.Thread.Sleep(TimeSpan.FromSeconds(10));   
  59.              /// /}   
  60.         }   


问题是解决了,后来再想了想,可以用WebClient先把页面download到本地临时文件,再读取文本内容。

代码如下:


  1. private   string  GetPageByWebClient( string  url)   
  2.          {   
  3.              string  result  =   null ;   
  4.              if  (url.Equals( " about:blank " ))  return   null ; ;   
  5.              if  ( ! url.StartsWith( " http:// " )  &&   ! url.StartsWith( " https:// " ))  { url  =   " http:// "   +  url; }   
  6.              string  filename  =  RandomKey( 1111 ,  9999 )  +   " .txt " ;   
  7.             DownloadOneFileByURLWithWebClient(filename, url,  " C:\\ " );   
  8.             StreamReader sr  =   new  StreamReader( " c:\\ "   +  filename, System.Text.Encoding.Default);   
  9.              try   { result  =  sr.ReadToEnd();  return  result; }   
  10.              catch   {  return   null ; }   
  11.              finally  
  12.              {   
  13.                  if  (sr  !=   null )  { sr.Close(); }   
  14.             }   
  15.         }   
  16.          private   string  RandomKey( int  b,  int  e)   
  17.          {   
  18.              return  DateTime.Now.ToString( " yyyyMMdd-HHmmss-fff- " )  +   this .getRandomID(b, e);   
  19.         }   
  20.          private   int  getRandomID( int  minValue,  int  maxValue)   
  21.          {   
  22.             Random ri  =   new  Random( unchecked (( int )DateTime.Now.Ticks));   
  23.              int  k  =  ri.Next(minValue, maxValue);   
  24.              return  k;   
  25.         }   
  26.          private   string  GuidString   
  27.          {   
  28.              get   {  return  Guid.NewGuid().ToString(); }   
  29.         }   
  30.      /**/ /// Web Client Method ,only For Small picture   
  31.          ///   </summary>   
  32.          ///   <param name="fileName"></param>   
  33.          ///   <param name="url"></param>   
  34.          ///   <param name="localPath"></param>   
  35.          public   static   void  DownloadOneFileByURLWithWebClient( string  fileName,  string  url,  string  localPath)   
  36.          {   
  37.             System.Net.WebClient wc  =   new  System.Net.WebClient();   
  38.              if  (File.Exists(localPath  +  fileName))  { File.Delete(localPath  +  fileName); }   
  39.              if  (Directory.Exists(localPath)  ==   false )  { Directory.CreateDirectory(localPath); }   
  40.             wc.DownloadFile(url  +  fileName, localPath  +  fileName);   
  41.         }   



结果不能获取源码。错误如下:邀月工作室

再想想,还有Webbrowser控件可以用啊。在WinFrom下只要在主线程前加[STAThread]即可。

  1. [STAThread]   
  2.          public   void  GetURLContentByWebBrowser()   
  3.          {   
  4.              try  
  5.              {   
  6.                  // webBrowser1 = new WebBrowser();   
  7.                  string  url  =  txtUrl.Text.Trim();   
  8.                  string  result  =   null ;   
  9.                 WebBrowser wb  =   new  WebBrowser();   
  10.                  /**/ /// /if (wb != null){ wb.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(wb_DocumentCompleted); }   
  11.                  if  (String.IsNullOrEmpty(url))  return ;   
  12.                  if  (url.Equals( " about:blank " ))  return ; ;   
  13.                  if  ( ! url.StartsWith( " http:// " )  &&   ! url.StartsWith( " https:// " ))  { url  =   " http:// "   +  url; }   
  14.                  try  
  15.                  {   
  16.                     wb.Navigate( new  Uri(url));   
  17.                     result  =  wb.DocumentText;   
  18.                     lbResult.Text  =  result;   
  19.                 }   
  20.                  catch  (System.UriFormatException)   
  21.                  { }   
  22.                  return ;   
  23.             }   
  24.              catch  (Exception ex)   
  25.              {   
  26.                  // WriteLog.Writelog("这是获取页面全部html代码时发生的错误:" + url, ex);    
  27.                  throw  ex;   
  28.                  // return ;   
  29.             }   
  30.         }   



在WebForm就麻烦些了,出现错误,线程不在单线程单元中,故无法实例化 ActiveX 控件“8856f961-340a-11d0-a96b-00c04fd705a2” 

邀月工作室

代码如下:
  1. private   string  GetPageStringbyWebBrowser( string  url)   
  2.          {   
  3.              if  (url.Equals( " about:blank " ))  return   null ; ;   
  4.              if  ( ! url.StartsWith( " http:// " )  &&   ! url.StartsWith( " https:// " ))  { url  =   " http:// "   +  url; }   
  5.             WebBrowser myWB  =   new  WebBrowser();   
  6.             myWB.ScrollBarsEnabled  =   false ;   
  7.             myWB.Navigate(url);   
  8.              while  (myWB.ReadyState  !=  WebBrowserReadyState.Complete)   
  9.              {   
  10.                 System.Windows.Forms.Application.DoEvents();   
  11.             }   
  12.              if  (myWB  !=   null )   
  13.              {   
  14.                 System.IO.StreamReader getReader  =   null ;   
  15.                  try  
  16.                  {   
  17.                     getReader  =   new  System.IO.StreamReader(myWB.DocumentStream, System.Text.Encoding.GetEncoding(myWB.Document.Encoding));   
  18.                      string  gethtml  =  getReader.ReadToEnd();   
  19.                      return  gethtml;   
  20.                 }   
  21.                  catch   {  return   null ; }   
  22.                  finally  
  23.                  {   
  24.                      if  (getReader  !=   null )  { getReader.Close(); }   
  25.                     myWB.Dispose();   
  26.                 }   
  27.             }   
  28.              return   null ;   
  29.         }   

 

后来搜索N小时(N>=5)后,终于找到可行解决方案,在WebPage页面头部加入AspCompat="true"

即<%@ Page Language="C#"  AspCompat="true" ******/>

MSDN给出的解释是:
在 ASP .NET 网页的 <%@Page> 标记中包含兼容性属性 aspcompat=true,如 <%@Page aspcompat=true Language=VB%>。使用此属性将强制网页以 STA 模式执行,从而确保您的组件可以继续正确运行。如果试图使用 STA 组件但没有指定此标记,运行时将会发生异常情况。

将此属性的值设置为 true 时,将允许网页调用 COM+ 1.0 组件,该组件需要访问非管理的 ASP 内置对象。可以通过 ObjectContext 对象进行访问。

如果将此标记的值设为 true,性能会稍微有些下降。建议只在确实需要时才这样做。


终于可以了! 不知道有没有更好的方法??



邀月工作室



附:源码下载。

邀月注:

如果不能测试,请注意是否在域(AD)环境下,如果是! 请注意设置代理和防火墙

posted on 2009-08-18 15:40  夏雷  阅读(1140)  评论(0编辑  收藏  举报