Получить 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 в источнике веб-страницы?

ggcodes
источник
Зависит от того, насколько умным должен быть поиск. Простой Containsзвонок может быть «достаточно хорошим».
ashes999
5
Изучите возможность использования пакета HTMLAgility, Fizzler или CSQuery, чтобы получить div / текст после того, как у вас есть HTML, все остальное слишком подвержено ошибкам.
jammykam
возможный дубликат Как мне загрузить исходный код HTML на C #
Джордж Дакетт,
@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
Mathieu 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 .

Tickseeker
источник
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);
        }
Юсеф
источник