2010-01-31 7 views
2

j'ai inspiré de l'exemple spectacle dans l'URL suivante csharp-online et destiné à récupérer toutes les URL de cette page alexaURL à l'aide regex Extraction dans .NET

using System; 
using System.Collections; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Net; 
using System.Text.RegularExpressions; 
namespace ExtractingUrls 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      WebClient client = new WebClient(); 
      const string url = "http://www.alexa.com/topsites/category/Top/Society/History/By_Topic/Science/Engineering_and_Technology"; 
      string source = client.DownloadString(url); 
      //Console.WriteLine(Getvals(source)); 
      string matchPattern = 
        @"<a.rel=""nofollow"".style=""font-size:0.8em;"".href=[""'](?<url>[^""^']+[.]*)[""'].class=""offsite"".*>(?<name>[^<]+[.]*)</a>"; 
      foreach (Hashtable grouping in ExtractGroupings(source, matchPattern, true)) 
      { 
       foreach (DictionaryEntry DE in grouping) 
       { 
        Console.WriteLine("Value = " + DE.Value); 
        Console.WriteLine(""); 
       } 
      } 
      // End. 
      Console.ReadLine(); 
     } 
     public static ArrayList ExtractGroupings(string source, string matchPattern, bool wantInitialMatch) 
     { 
      ArrayList keyedMatches = new ArrayList(); 
      int startingElement = 1; 
      if (wantInitialMatch) 
      { 
       startingElement = 0; 
      } 
      Regex RE = new Regex(matchPattern, RegexOptions.Multiline); 
      MatchCollection theMatches = RE.Matches(source); 
      foreach (Match m in theMatches) 
      { 
       Hashtable groupings = new Hashtable(); 
       for (int counter = startingElement; counter < m.Groups.Count; counter++) 
       { 
        // If we had just returned the MatchCollection directly, the 
        // GroupNameFromNumber method would not be available to use 
        groupings.Add(RE.GroupNameFromNumber(counter), 
        m.Groups[counter]); 
       } 
       keyedMatches.Add(groupings); 
      } 
      return (keyedMatches); 
     } 
    } 
} 

Mais ici je fais face à un problème, Lorsque j'exécute chaque URL s'affiche trois fois, c'est d'abord l'ensemble de l'étiquette d'ancrage qui s'affiche, ensuite l'URL est affichée deux fois. Quelqu'un peut-il me suggérer où dois-je corriger afin que je puisse avoir chaque URL affichée exactement une fois.

+2

** DO _NOT_ parse HTML utilisant des expressions régulières ** http://stackoverflow.com/questions/1732348/regex-match-open-tags- except-xhtml-self-contained-tags – SLaks

+0

@SLacks: "il est parfois approprié d'analyser un ensemble limité et connu de HTML" –

Répondre

1

dans votre regex, vous avez deux groupes, et le match. Si je lis correctement, vous devriez vouloir que la partie URL des matches, qui est le deuxième des 3 groupes ....

au lieu de ceci:

for (int counter = startingElement; counter < m.Groups.Count; counter++) 
      { 
       // If we had just returned the MatchCollection directly, the 
       // GroupNameFromNumber method would not be available to use 
       groupings.Add(RE.GroupNameFromNumber(counter), 
       m.Groups[counter]); 
      } 

ne pas vous veulent cette ?:

groupings.Add(RE.GroupNameFromNumber(1),m.Groups[1]); 
3

Utilisez HTML Agility Pack pour analyser HTML. Je pense que cela rendra votre problème beaucoup plus facile à résoudre.

est ici une façon de le faire:

WebClient client = new WebClient(); 
string url = "http://www.alexa.com/topsites/category/Top/Society/History/By_Topic/Science/Engineering_and_Technology"; 
string source = client.DownloadString(url); 
HtmlDocument doc = new HtmlDocument(); 
doc.LoadHtml(source); 
foreach (HtmlNode link in doc.DocumentNode.SelectNodes("//a[@href and @rel='nofollow']")) 
{ 
    Console.WriteLine(link.Attributes["href"].Value); 
} 
1
int startingElement = 1; 
if (wantInitialMatch) 
{ 
startingElement = 0; 
} 

...

for (int counter = startingElement; counter < m.Groups.Count; counter++) 
{ 
// If we had just returned the MatchCollection directly, the 
// GroupNameFromNumber method would not be available to use 
    groupings.Add(RE.GroupNameFromNumber(counter), 
    .Groups[counter]); 
} 

Votre passage wantInitialMatch = true, de sorte que votre boucle est de retour:

.Groups[0] //entire match 
.Groups[1] //(?<url>[^""^']+[.]*) href part 
.Groups[2] //(?<name>[^<]+[.]*) link text 
+0

Merci paul, maintenant j'ai compris où je me suis trompé. – Chaitanya