Obtenir le code HTML du site Web en C #

87

Comment obtenir le code HTML d'un site Web, l'enregistrer et trouver du texte par une expression LINQ?

J'utilise le code suivant pour obtenir la source d'une page Web:

public static String code(string Url)
{
    HttpWebRequest myRequest = (HttpWebRequest)WebRequest.Create(Url);
    myRequest.Method = "GET";
    WebResponse myResponse = myRequest.GetResponse();
    StreamReader sr = new StreamReader(myResponse.GetResponseStream(), System.Text.Encoding.UTF8);
    string result = sr.ReadToEnd();
    sr.Close();
    myResponse.Close();

    return result;
 }

Comment trouver le texte d'un div dans la source de la page Web?

ggcodes
la source
Cela dépend de la manière dont la recherche intelligente devrait être. Un simple Containsappel peut être «assez bon».
ashes999
5
Essayez d'utiliser HTMLAgility pack, Fizzler ou CSQuery pour obtenir le div / texte une fois que vous avez le HTML, tout le reste est trop sujet aux erreurs.
jammykam
duplication possible de Comment puis-je télécharger la source HTML en C #
George Duckett
@GeorgeDuckett Cela ne ressemble pas à un double de cette question, la question à laquelle vous liez ne concerne que la récupération de la source, cette question concerne également l'interrogation du DOM.
Mark Rotteveel
@Mark: Désolé, vous avez tout à fait raison, vous avez manqué le texte en bas.
George Duckett

Réponses:

112

Obtenir du code HTML à partir d'un site Web. Vous pouvez utiliser un code comme celui-ci.

string urlAddress = "http://google.com";

HttpWebRequest request = (HttpWebRequest)WebRequest.Create(urlAddress);
HttpWebResponse response = (HttpWebResponse)request.GetResponse();

if (response.StatusCode == HttpStatusCode.OK)
{
  Stream receiveStream = response.GetResponseStream();
  StreamReader readStream = null;

  if (String.IsNullOrWhiteSpace(response.CharacterSet))
     readStream = new StreamReader(receiveStream);
  else
     readStream = new StreamReader(receiveStream, Encoding.GetEncoding(response.CharacterSet));

  string data = readStream.ReadToEnd();

  response.Close();
  readStream.Close();
}

Cela vous donnera le code HTML renvoyé par le site Web. Mais trouver du texte via LINQ n'est pas si simple. Il est peut-être préférable d'utiliser une expression régulière mais cela ne fonctionne pas bien avec le code HTML

Erreur de syntaxe
la source
4
L'idée d'utiliser des regex pour html ou XML est TRÈS mauvaise pratique de codage ... Aller à votre façon - nous devrions utiliser le mot-clé goto partout ...
Lightning3
En fait, l'utilisation de regex pour rechercher une chose précise dans le code HTML peut être une solution très décente. Tenter de construire un analyseur / interpréteur HTML basé sur regex, en revanche, serait une pure folie. Tout dépend du contexte et de la tâche réelle qui doit être effectuée, mais dire que «l'expression régulière ne joue jamais bien avec HTML» n'est tout simplement pas une vérité globale et inaliénable. stackoverflow.com/a/1733489/6838730
Mathieu VIALES
177

Mieux vous pouvez utiliser la classe Webclient pour simplifier votre tâche:

using System.Net;

using (WebClient client = new WebClient())
{
    string htmlCode = client.DownloadString("http://somesite.com/default.html");
}
Santosh Panda
la source
Une idée pourquoi j'obtiens cette erreur? 'System.Net.WebClient': le type utilisé dans une instruction using doit être implicitement convertible en 'System.IDisposable'
Dave Chandler
9
Pour l' usingexigence clairement indiqué pour tout le monde à utiliser: +1
user3916429
37

La meilleure chose à utiliser est HTMLAgilityPack . Vous pouvez également envisager d'utiliser Fizzler ou CSQuery en fonction de vos besoins pour sélectionner les éléments de la page récupérée. L'utilisation d'expressions LINQ ou Regukar est juste sujette aux erreurs, en particulier lorsque le HTML peut être malformé, manquer des balises de fermeture, avoir des éléments enfants imbriqués, etc.

Vous devez diffuser la page dans un objet HtmlDocument, puis sélectionner l'élément requis.

// Call the page and get the generated HTML
var doc = new HtmlAgilityPack.HtmlDocument();
HtmlAgilityPack.HtmlNode.ElementsFlags["br"] = HtmlAgilityPack.HtmlElementFlag.Empty;
doc.OptionWriteEmptyNodes = true;

try
{
    var webRequest = HttpWebRequest.Create(pageUrl);
    Stream stream = webRequest.GetResponse().GetResponseStream();
    doc.Load(stream);
    stream.Close();
}
catch (System.UriFormatException uex)
{
    Log.Fatal("There was an error in the format of the url: " + itemUrl, uex);
    throw;
}
catch (System.Net.WebException wex)
{
    Log.Fatal("There was an error connecting to the url: " + itemUrl, wex);
    throw;
}

//get the div by id and then get the inner text 
string testDivSelector = "//div[@id='test']";
var divString = doc.DocumentNode.SelectSingleNode(testDivSelector).InnerHtml.ToString();

[EDIT] En fait, supprimez ça. La méthode la plus simple consiste à utiliser FizzlerEx , une implémentation mise à jour de jQuery / CSS3-selectors du projet Fizzler original.

Exemple de code directement depuis leur site:

using HtmlAgilityPack;
using Fizzler.Systems.HtmlAgilityPack;

//get the page
var web = new HtmlWeb();
var document = web.Load("http://example.com/page.html");
var page = document.DocumentNode;

//loop through all div tags with item css class
foreach(var item in page.QuerySelectorAll("div.item"))
{
    var title = item.QuerySelector("h3:not(.share)").InnerText;
    var date = DateTime.Parse(item.QuerySelector("span:eq(2)").InnerText);
    var description = item.QuerySelector("span:has(b)").InnerHtml;
}

Je ne pense pas que cela puisse être plus simple que cela.

jammykam
la source
Que faire si je souhaite appeler un bouton spécifique sur la page Web? @jammykam
Jamshaid Kamran
1
Vous ne pouvez pas faire cela avec un grattoir d'écran afaik, vous devrez utiliser quelque chose comme Selenium pour appeler le bouton.
jammykam
Comment installez-vous FizzlerEx? Je vérifie le lien et il y a un .zip mais je ne vois aucun installateur
Juan Carlos Oropeza
5

J'utilise AngleSharp et j'en suis très satisfait.

Voici un exemple simple de récupération d'une page:

var config = Configuration.Default.WithDefaultLoader();
var document = await BrowsingContext.New(config).OpenAsync("https://www.google.com");

Et maintenant, vous avez une page Web dans la variable de document . Ensuite, vous pouvez facilement y accéder par LINQ ou d'autres méthodes. Par exemple, si vous souhaitez obtenir une valeur de chaîne à partir d'un tableau HTML:

var someStringValue = document.All.Where(m =>
        m.LocalName == "td" &&
        m.HasAttribute("class") &&
        m.GetAttribute("class").Contains("pid-1-bid")
    ).ElementAt(0).TextContent.ToString();

Pour utiliser les sélecteurs CSS, veuillez consulter les exemples d'AngleSharp .

Tickseeker
la source
5

Voici un exemple d'utilisation de la HttpWebRequestclasse pour récupérer une URL

private void buttonl_Click(object sender, EventArgs e) 
{ 
    String url = TextBox_url.Text;
    HttpWebRequest request = (HttpWebRequest) WebRequest.Create(url); 
    HttpWebResponse response = (HttpWebResponse) request.GetResponse(); 
    StreamReader sr = new StreamReader(response.GetResponseStream()); 
    richTextBox1.Text = sr.ReadToEnd(); 
    sr.Close(); 
} 
Mohamed Sayed
la source
2
vous devez ajouter du code dans votre réponse au lieu d'une image.
AJ
2

Vous pouvez utiliser WebClient pour télécharger le html pour n'importe quelle URL. Une fois que vous avez le html, vous pouvez utiliser une bibliothèque tierce comme HtmlAgilityPack pour rechercher des valeurs dans le html comme dans le code ci-dessous -

public static string GetInnerHtmlFromDiv(string url)
    {
        string HTML;
        using (var wc = new WebClient())
        {
            HTML = wc.DownloadString(url);
        }
        var doc = new HtmlAgilityPack.HtmlDocument();
        doc.LoadHtml(HTML);
        
        HtmlNode element = doc.DocumentNode.SelectSingleNode("//div[@id='<div id here>']");
        if (element != null)
        {
            return element.InnerHtml.ToString();
        }   
        return null;            
    }
Ghanendra Singh
la source
1

Essayez cette solution. Ça fonctionne bien.

 try{
        String url = textBox1.Text;
        HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
        HttpWebResponse response = (HttpWebResponse)request.GetResponse();
        StreamReader sr = new StreamReader(response.GetResponseStream());
        HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
        doc.Load(sr);
        var aTags = doc.DocumentNode.SelectNodes("//a");
        int counter = 1;
        if (aTags != null)
        {
            foreach (var aTag in aTags)
            {
                richTextBox1.Text +=  aTag.InnerHtml +  "\n" ;
                counter++;
            }
        }
        sr.Close();
        }
        catch (Exception ex)
        {
            MessageBox.Show("Failed to retrieve related keywords." + ex);
        }
youssef
la source