Dump Hrefs


13 April 2002 @ 21:04

Her bliver vist hvordan man kan downloade fra en url og efterfølgende behandle den downloadede data med Regular Expressions, som f.eks. at udtrække alle url's fra siden.


af Anders Bodeval Carlsen

Da jeg begyndte at udforske .NET løb jeg ind i klasserne Uri og Regex.
- To særdelse gode argumenter for at droppe den trygge og vante spagettikode.
og begynde at smage på .NET

Uri bruges til at oprette et link objekt, mens Regex bruges til at håndterer Regular Expression, som er kraftigt understøttet i .NET.

Uri klassen har sparet mig for adskillige timers arbejde med at lave en kode som kan omformaterer en relativ adresse til en absolut adresse.

Her vil du finde eksempler på anvendelse af disse to klasser m.m.

Der er en funktion til at hente indholdet af en hjemmeside på en given adresse.
Der er en funktion der ved hjælp af Regular Expressions trække indholdet af en given html kode ud af den hentede tekst.
I dette tilfælde findes siden titel .
Og en funktion der finder alle href-koder i den hentede tekst og omformatere adresserne til absolutte adresser, så de kan bruges lokalt.


For dem der ikke har opdaget det, så er .Net Frameworket en næsten altomfattende pakkeløsning, og med i denne pakke følge den enormt gode FrameWork SDK. Jeg har endnu ikke oplevet at sidde fast pga. manglende dukumentation. En søgning i SDK'en bringer mig altid videre.

Så søg på Uri Eller Regex i SDK'en hvis du ønsker en uddybning af disse klasser.

Jeg alligevel vil fokuserer på nogle stumper af koden.

   Regex r = new Regex("href\\s*=\\s*(?:\"(?<1>[^\"]*)\")",
   RegexOptions.IgnoreCase|RegexOptions.Compiled);


   for (Match m = r.Match(inputString); m.Success; m = m.NextMatch()) 
   {
      urlTxt = m.Groups[1].Value; .......

Der søges i en teksstreng og alle href="..." værdier findes.
Herefter gennemløbes Match objektet for at finde de enkelte forekomster af href's


         tempUri = new Uri(baseUri, urlTxt);
         result += "<a href=\"" + tempUri.AbsoluteUri + "\" title=\"" + urlTxt + "\">" + tempUri.AbsoluteUri +             "</a><br>\n";

Der konstrueres et Uri Objekt med new Uri(baseUri, urlTxt);
Base Uri kunne f.eks. være "http://www.activedeveloper.dk" og urlTxt kunne være "/download/"
tempUri.AbsoluteUri ville så returnere : http://www.activedeveloper.dk/download/




DumpHrefs.aspx

<% @Page Language="C#" Debug="false" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.Net" %>
<script Language="C#" runat="server">
   void Page_Load(Object sender, EventArgs e) {
      if (!Page.IsPostBack) {
         Uri.Text = @"http://www.activedeveloper.dk";
      }

   }

   void OkBtn_Click(Object sender, EventArgs e) {
      String htmlText = "";
      // Her henter jeg siden
      htmlText = getUrl(Uri.Text); 

      // Finder sidens titel
      MyDiv.InnerHtml = "<h3>" + Server.HtmlEncode(DumpHtmlCodes(htmlText, "title")) + "</h3>";

      MyDiv.InnerHtml += "<b>" + Server.HtmlEncode(Uri.Text) + "</b><br>\n";

      // 
      MyDiv.InnerHtml += "<pre>" + Server.HtmlEncode(htmlText.Substring(0,htmlText.Length > 600 ? 600 :                   htmlText.Length )) + ".............</pre><br>\n";

      MyDiv.InnerHtml += DumpHrefs(htmlText, new Uri(Uri.Text));
   }

   public String DumpHtmlCodes(String inputString, String codeName) 
   {
      // Funktionen returnerer den første forekomst af htmlkoden codename
      String code = @"<" + codeName + ">(.*?)<\\/" + codeName + ">";
      Regex tit = new Regex(code,RegexOptions.IgnoreCase|RegexOptions.Compiled|RegexOptions.Singleline);
      Match m = tit.Match(inputString);
      return m.Groups[1].Value;
   }

   public String DumpHrefs(String inputString, Uri baseUri)
   {

   // Funktionen finder alle links i en html-kode fra en bestemt adresse.
   // Urien på de enkelte links ændres fra en eventuel relativ-adresse til en absulut adresse.
   // Der returneres en liste med de omformaterede links på siden.

   String result = "";
   String urlTxt = "";
   Uri tempUri;

   // Nedenstående expression virker, men sikkert ikke i alle tilfælde 
   // da der er et næsten uendeligt antal special tilfælde, som der ikke er taget højde for.
   Regex r = new Regex("href\\s*=\\s*(?:\"(?<1>[^\"]*)\")",
   RegexOptions.IgnoreCase|RegexOptions.Compiled);

   for (Match m = r.Match(inputString); m.Success; m = m.NextMatch()) 
   {
      urlTxt = m.Groups[1].Value;

      try {
         tempUri = new Uri(baseUri, urlTxt);
         result += "<a href=\"" + tempUri.AbsoluteUri + "\" title=\"" + urlTxt + "\">" + tempUri.AbsoluteUri +             "</a><br>\n";
      }
   
      // Eventueller fejlformaterede uri'er fanges her
      catch(UriFormatException ex) {
         result += "error in uri: " + urlTxt + "\n" + ex; 
      }

   // Alle andre fejl fanges her. 
   catch(Exception ex) {
      result += "error in uri: " + urlTxt + "\n" + ex; 
   }
   }
   return result;
}

   public String getUrl(String surl)
   {
      // Funktionen returnerer en tekststreng med svaret fra en url
      String result = "";

      WebRequest req = WebRequest.Create(surl);

      try
      {
         WebResponse reqresult = req.GetResponse();
         Stream ReceiveStream = reqresult.GetResponseStream();

         Byte[] read = new Byte[512];
         int bytes = ReceiveStream.Read(read, 0, 512);

         while (bytes > 0)
         {
            result += System.Text.Encoding.Default.GetString(read, 0, bytes);
            bytes = ReceiveStream.Read(read, 0, 512);
         }

         return result;
     }
      catch(WebException w) 
      { 
         return "Error in Response stream, ...:" + w;
      }
   }

</script>

<html>
<body>
<h1 id="Overskrift" runat="server" >Strip Url's</h1>
<form runat="server">
      <asp:TextBox id="Uri" size="75" runat="server" />
      <asp:Button id="updateButton" Text="Ok" runat="server" OnClick="OkBtn_Click" />
</form>
   <div runat="server" id="MyDiv" />
</body>
</html>

 


Valid XHTML 1.0!