2012-07-25 2 views
4

Je cherche une méthode qui me permettra d'obtenir le titre d'une page Web et de le stocker sous forme de chaîne.Comment obtenir le titre de la page Web sans télécharger toute la page source

Cependant, toutes les solutions que j'ai trouvées jusqu'ici impliquent le téléchargement du code source de la page, ce qui n'est pas vraiment pratique pour un grand nombre de pages Web. La seule façon que je pourrais voir serait de limiter la longueur de la chaîne ou il télécharge seulement un certain nombre de caractères ou d'arrêts une fois qu'il atteint la balise, mais cela sera évidemment encore assez grand?

Merci

Répondre

13

Comme la balise <title> est dans le code HTML lui-même, il n'y aura aucun moyen de ne pas télécharger le fichier pour trouver « juste le titre. » Vous devriez pouvoir télécharger une partie du fichier jusqu'à ce que vous ayez lu la balise <title>, ou la balise </head>, puis arrêtez, mais vous devrez tout de même télécharger (au moins une partie) du fichier.

Ceci peut être accompli avec HttpWebRequest/HttpWebResponse et la lecture des données du flux de réponse jusqu'à ce que nous avons soit lu dans un bloc <title></title>, ou l'étiquette </head>. J'ai ajouté la vérification des étiquettes </head> car, en HTML valide, le cartouche doit apparaître dans le bloc de tête - ainsi, avec cette vérification, nous n'analyserons jamais le fichier en entier (sauf s'il n'y a pas de bloc de tête, bien sûr).

Les points suivants doivent être en mesure d'accomplir cette tâche:

string title = ""; 
try { 
    HttpWebRequest request = (HttpWebRequest.Create(url) as HttpWebRequest); 
    HttpWebResponse response = (request.GetResponse() as HttpWebResponse); 

    using (Stream stream = response.GetResponseStream()) { 
     // compiled regex to check for <title></title> block 
     Regex titleCheck = new Regex(@"<title>\s*(.+?)\s*</title>", RegexOptions.Compiled | RegexOptions.IgnoreCase); 
     int bytesToRead = 8092; 
     byte[] buffer = new byte[bytesToRead]; 
     string contents = ""; 
     int length = 0; 
     while ((length = stream.Read(buffer, 0, bytesToRead)) > 0) { 
      // convert the byte-array to a string and add it to the rest of the 
      // contents that have been downloaded so far 
      contents += Encoding.UTF8.GetString(buffer, 0, length); 

      Match m = titleCheck.Match(contents); 
      if (m.Success) { 
       // we found a <title></title> match =] 
       title = m.Groups[1].Value.ToString(); 
       break; 
      } else if (contents.Contains("</head>")) { 
       // reached end of head-block; no title found =[ 
       break; 
      } 
     } 
    } 
} catch (Exception e) { 
    Console.WriteLine(e); 
} 

MISE À JOUR: mis à jour la source d'origine par exemple d'utiliser un compilé Regex et une déclaration using pour la Stream pour une meilleure efficacité et la maintenabilité.

+1

Je donnerais +2 pour le visage triste sur le dernier commentaire mais je ne peux pas = [ – Charleh

+1

Ceci est une bonne solution de code, merci. FYI - Le problème avec regex compilé est qu'il ne va pas vraiment aider ici, parce que vous compilez l'expression rationnelle pour chaque demande. Il serait préférable de le compiler une fois lors de l'exécution puis de l'utiliser dans cette méthode. La compilation prend un peu de temps et beaucoup plus de mémoire, mais elle est idéale pour les documents volumineux (100mb +) ou les boucles (centaines de milliers). Regex non compilé est mis en cache et pour la taille de ce texte n'a pas vraiment d'effet. +1 – ppumkin

1

Une façon plus simple de gérer ce serait de le télécharger, puis divisé:

using System; 
    using System.Net.Http; 

    private async void getSite(string url) 
    { 
     HttpClient hc = new HttpClient(); 
     HttpResponseMessage response = await hc.GetAsync(new Uri(url, UriKind.Absolute)); 
     string source = await response.Content.ReadAsStringAsync(); 

     //process the source here 

    } 

Pour traiter la source, vous pouvez utiliser la méthode décrite ici dans l'article sur Getting Content From Between HTML Tags

+0

Pour améliorer la qualité de votre message, veuillez indiquer comment/pourquoi ce code résoudra le problème. –

Questions connexes