C # 'da web sitesinden HTML kodu alın


89

Bir web sitesinden HTML kodu nasıl alınır, kaydedilir ve bir LINQ ifadesiyle metin nasıl bulunur?

Bir web sayfasının kaynağını almak için aşağıdaki kodu kullanıyorum:

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;
 }

Web sayfasının kaynağındaki bir div'deki metni nasıl bulurum?


Akıllı aramanın ne kadar olması gerektiğine bağlı. Basit bir Containsarama "yeterince iyi" olabilir.
ashes999

5
HTML'ye sahip olduğunuzda div / metni almak için HTMLAgility paketi, Fizzler veya CSQuery kullanmaya bakın, diğer her şey hataya çok açıktır.
jammykam


@GeorgeDuckett Bu sorunun bir kopyası gibi görünmüyor, bağlantı verdiğiniz soru yalnızca kaynağı almakla ilgili, bu soru aynı zamanda DOM'u sorgulamakla ilgili.
Mark Rotteveel

@Mark: Üzgünüm, haklısınız, alttaki metni kaçırdınız.
George Duckett

Yanıtlar:


113

Bir web sitesinden HTML kodu almak. Kodu böyle kullanabilirsiniz.

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();
}

Bu size web sitesinden döndürülen HTML kodunu verecektir . Ancak LINQ aracılığıyla metin bulmak o kadar kolay değil. Belki de normal ifade kullanmak daha iyidir, ancak bu HTML koduyla pek iyi sonuç vermez


4
Html veya XML için regex kullanma fikri ÇOK kötü bir kodlama uygulamasıdır ... Size Giden Yol - her yerde goto anahtar kelimesini kullanmalıyız ...
Lightning3

1
Aslında, HTML kodu içinde kesin bir şeyi aramak için normal ifadeyi kullanmak çok iyi bir çözüm olabilir. Öte yandan, normal ifadeye dayalı bir HTML ayrıştırıcı / yorumlayıcı oluşturmaya çalışmak tam bir çılgınlık olur. Her şey bağlama ve yerine getirilmesi gereken gerçek göreve bağlıdır, ancak "regex'in HTML ile hiçbir zaman iyi oynamadığını" söylemek küresel, yenilmez bir gerçek değildir. stackoverflow.com/a/1733489/6838730
Mathieu VIALES

183

Daha iyisi, görevinizi basitleştirmek için Webclient sınıfını kullanabilirsiniz:

using System.Net;

using (WebClient client = new WebClient())
{
    string htmlCode = client.DownloadString("http://somesite.com/default.html");
}

Bu hatayı neden aldığım hakkında bir fikriniz var mı? 'System.Net.WebClient': using ifadesinde kullanılan tür örtük olarak 'System.IDisposable'a dönüştürülebilir olmalıdır
Dave Chandler

10
İçin using1: Açıkça kullanımına herkes için gösterilen gereksinimi
user3916429

Http 403 hatası alanlar için client.Headers.Add ("user-agent", "Fiddler"); Fiddler'ı istediğiniz herhangi bir metinle değiştirin.
Himanshu Patel

37

Kullanılacak en iyi şey HTMLAgilityPack'tir . Ayrıca , alınan sayfadaki öğeleri seçme ihtiyaçlarınıza bağlı olarak Fizzler veya CSQuery kullanmayı da inceleyebilirsiniz . LINQ veya Regukar İfadelerini kullanmak, özellikle HTML hatalı biçimlendirilebildiğinde, kapanış etiketleri eksik olduğunda, iç içe geçmiş alt öğelere sahip olduğunda vb. Hataya açıktır.

Sayfayı bir HtmlDocument nesnesine aktarmanız ve ardından gerekli öğeyi seçmeniz gerekir.

// 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();

[DÜZENLE] Aslında bunu bir kenara bırakın. En basit yöntem kullanmaktır FizzlerEx , orijinal Fizzler projenin güncelleştirilmiş jQuery / CSS3-seçiciler uygulanmasını.

Doğrudan kendi sitelerinden kod örneği:

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;
}

Bundan daha basit olabileceğini sanmıyorum.


Web sayfasındaki belirli bir düğmeyi çağırmak istersem ne olur? @jammykam
Jamshaid K.

1
Bunu bir ekran kazıyıcıyla yapamazsınız afaik, düğmeyi çağırmak için Selenium gibi bir şey kullanmanız gerekir.
jammykam

FizzlerEx'i nasıl kurarsınız? Bağlantıyı kontrol ediyorum ve bir .zip var ama herhangi bir yükleyici göremiyorum
Juan Carlos Oropeza

6

AngleSharp kullanıyorum ve bundan çok memnun kaldım.

İşte bir sayfanın nasıl getirileceğine dair basit bir örnek:

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

Ve şimdi belge değişkeninde bir web sayfanız var . Ardından, LINQ veya diğer yöntemlerle kolayca erişebilirsiniz. Örneğin, bir HTML tablosundan bir dize değeri almak istiyorsanız:

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

CSS seçicilerini kullanmak için lütfen AngleSharp örneklerine bakın .


5

HttpWebRequestBir URL'yi getirmek için sınıfı kullanma örneğini burada bulabilirsiniz

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(); 
} 

2
cevabınıza resim yerine kod eklemelisiniz.
AJ

2

Herhangi bir url için html'yi indirmek için WebClient'ı kullanabilirsiniz. Html'ye sahip olduğunuzda, aşağıdaki kodda olduğu gibi html'deki değerleri aramak için HtmlAgilityPack gibi üçüncü taraf bir kitaplığı kullanabilirsiniz -

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;            
    }

1

Bu çözümü deneyin. İyi çalışıyor.

 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);
        }
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.