Отримати HTML-код із веб-сайту на C #


87

Як отримати HTML-код із веб-сайту, зберегти його та знайти текст за виразом LINQ?

Я використовую такий код, щоб отримати джерело веб-сторінки:

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

Як знайти текст у div у джерелі веб-сторінки?


Залежить від того, наскільки розумним повинен бути пошук. Простий Containsдзвінок може бути "достатньо хорошим".
попіл999

5
Зверніть увагу на використання пакета HTMLAgility, Fizzler або CSQuery, щоб отримати div / текст, коли у вас є HTML, все інше занадто схильне до помилок.
jammykam


@GeorgeDuckett Це не схоже на дублікат цього запитання, питання, на яке ви посилаєтесь, стосується лише отримання джерела, це питання також стосується запиту DOM.
Марк Роттівел

@Mark: Вибачте, ви цілком праві, пропустили текст внизу.
Джордж Дакетт

Відповіді:


112

Отримання HTML-коду з веб-сайту. Ви можете використовувати такий код.

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

Це дасть вам повернутий HTML- код із веб-сайту. Але знайти текст за допомогою LINQ не так просто. Можливо, краще використовувати регулярний вираз, але це погано поєднується з HTML- кодом


4
Ідея використання регулярного виразу для html або XML є ДУЖЕ поганою практикою кодування ... Йдучи вашим шляхом - ми повинні використовувати ключове слово goto скрізь ...
Lightning3

Насправді, використання регулярного виразу для пошуку точної речі в HTML-коді може бути цілком пристойним рішенням. З іншого боку, спроба побудувати синтаксичний аналізатор / інтерпретатор HTML на основі регулярного виразу буде чистим божевіллям. Все залежить від контексту та фактичного завдання, яке потрібно виконати, але сказати, що "регулярний вираз ніколи не грає добре з HTML", просто не є глобальною, неможливою істиною. stackoverflow.com/a/1733489/6838730
Матьє Viales

177

Краще ви можете використовувати клас Webclient для спрощення свого завдання:

using System.Net;

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

Будь-яка ідея, чому я отримую цю помилку? 'System.Net.WebClient': тип, що використовується в операторі using, повинен неявно конвертуватися в 'System.IDisposable'
Дейв Чандлер

9
Для usingвимоги, чітко показаної для використання всіма: +1
user3916429

37

Найкраще використовувати HTMLAgilityPack . Ви також можете вивчити використання Fizzler або CSQuery залежно від ваших потреб у виборі елементів із отриманої сторінки. Використання LINQ або Regukar Expressions призводить лише до помилок, особливо коли HTML може бути неправильно сформований, відсутні теги закриття, вкладені дочірні елементи тощо

Вам потрібно передати сторінку в об’єкт HtmlDocument, а потім вибрати потрібний елемент.

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

[РЕДАКТУВАТИ] Насправді, відкиньте це. Найпростіший метод - використовувати FizzlerEx , оновлену реалізацію jQuery / CSS3-селекторів оригінального проекту Fizzler.

Зразок коду безпосередньо з їх сайту:

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

Я не думаю, що це може стати простішим.


Що робити, якщо я хочу викликати певну кнопку на веб-сторінці? @jammykam
Джамшаїд Камран

1
Ви не можете цього зробити за допомогою скребка для екрану afaik, вам доведеться використовувати щось на зразок Selenium, щоб викликати кнопку.
jammykam

Як ви встановлюєте FizzlerEx? Я перевіряю посилання і є файл .zip, але я не бачу жодного інсталятора
Хуан Карлос Оропеза

5

Я використовую AngleSharp і був дуже задоволений нею.

Ось простий приклад отримання сторінки:

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

І тепер у вас є веб-сторінка зі змінною документа . Тоді ви можете легко отримати до нього доступ за допомогою LINQ або іншими методами. Наприклад, якщо ви хочете отримати значення рядка з таблиці HTML:

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

Щоб використовувати селектори CSS, перегляньте приклади AngleSharp .


5

Ось приклад використання HttpWebRequestкласу для отримання 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(); 
} 

2
вам слід додати код у свою відповідь замість зображення.
AJ

2

Ви можете використовувати WebClient для завантаження html для будь-якої URL-адреси. Отримавши html, ви можете використовувати сторонні бібліотеки, такі як HtmlAgilityPack, для пошуку значень у html, як показано в коді нижче -

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

Спробуйте це рішення. Це чудово працює.

 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);
        }
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.