Як користуватися пакетом HTML Agility


629

Як я можу користуватися пакетом спритності HTML ?

Мій документ XHTML не повністю дійсний. Ось чому я хотів ним скористатися. Як я можу використовувати його у своєму проекті? Мій проект знаходиться в C #.


79
Це питання мені дуже допомогло.
BigJoe714

26
Бічна примітка: за допомогою Visual Studio, який обробляє NuGet, тепер ви можете клацнути правою кнопкою миші «Посилання» та вибрати «Управління пакетами NuGet ...», шукати «HtmlAgilityPack» та натискати «Встановити». Тоді вступайте в гру з кодом із використанням оператора / Import.
патрон

Щодо вищезазначеного коментаря від @patridge: я виявив, що мені потрібно видалити та повторно додати свою посилання на HtmlAgilityPack при першому завантаженні проекту із svn через ankhsvn.
Ендрю Кунсе

14
Кожен, хто заглядає в HTMLAgilityPack, повинен розглянути CsQuery, це набагато новіша бібліотека зі значно сучаснішим інтерфейсом з мого досвіду. Наприклад, весь код з першої відповіді можна підсумувати в CsQuery як var body = CQ.CreateFromFile(filePath)["body"].
Бенджамін Грюнбаум

2
@BenjaminGruenbaum: великі пальці для вашої пропозиції CsQuery - налаштовані за лічені хвилини, дуже прості у використанні.
Неоліск

Відповіді:


358

По-перше, встановіть пакет нуметів HTMLAgilityPack у свій проект.

Тоді, як приклад:

HtmlAgilityPack.HtmlDocument htmlDoc = new HtmlAgilityPack.HtmlDocument();

// There are various options, set as needed
htmlDoc.OptionFixNestedTags=true;

// filePath is a path to a file containing the html
htmlDoc.Load(filePath);

// Use:  htmlDoc.LoadHtml(xmlString);  to load from a string (was htmlDoc.LoadXML(xmlString)

// ParseErrors is an ArrayList containing any errors from the Load statement
if (htmlDoc.ParseErrors != null && htmlDoc.ParseErrors.Count() > 0)
{
    // Handle any parse errors as required

}
else
{

    if (htmlDoc.DocumentNode != null)
    {
        HtmlAgilityPack.HtmlNode bodyNode = htmlDoc.DocumentNode.SelectSingleNode("//body");

        if (bodyNode != null)
        {
            // Do something with bodyNode
        }
    }
}

(Примітка. Цей код є лише прикладом, а не обов'язково найкращим / єдиним підходом. Не використовуйте його наосліп у власній програмі.)

HtmlDocument.Load()Метод також приймає потік , який є дуже корисним для інтеграції з іншими потоковими орієнтованими класами в рамках .NET. Хоча HtmlEntity.DeEntitize()це ще один корисний метод для правильної обробки html-об'єктів. (дякую Метью)

HtmlDocumentі HtmlNode це класи, якими ви користуєтесь найбільше. Подібно до XML-аналізатора, він забезпечує методи selectSingleNode та selectNodes, які приймають вирази XPath.

Зверніть увагу на HtmlDocument.Option?????? булеві властивості. Вони контролюють, як Loadі LoadXMLметоди оброблять ваш HTML / XHTML.

Існує також складений довідковий файл під назвою HtmlAgilityPack.chm, який має повне посилання на кожен з об'єктів. Зазвичай це знаходиться в базовій папці рішення.


11
Також зауважте, що Load приймає параметр Stream, що зручно у багатьох ситуаціях. Я використовував його для потоку HTTP (WebResponse.GetResponseStream). Ще один хороший метод, про який слід пам’ятати, це HtmlEntity.DeEntitize (частина пакету HTML Agility). Це потрібно для обробки об'єктів вручну в деяких випадках.
Метью Флашен

1
Зауважте: в останній бета-версії пакету Html Agility Pack (1.4.0 Beta 2, випущена 3 жовтня 2009 р.) файл довідки було переміщено в окреме завантаження через залежності від Sandcastle, DocProject та SDK Visual Studio 2008.
rtpHarry

SelectSingleNode() здається, був видалений деякий час тому
Chris S

3
Ні, SelectSingleNode та SelectNodes, безумовно, все ще є. Мені здається трохи цікавим, що це має бути htmlDoc.ParseErrors.Count (), а не .Count
Майк Бландфорд

1
@MikeBlandford // Частково так. Здається, його видалили (або не існували з самого початку) у PCL-версії HtmlAgailityPack. nuget.org/packages/HtmlAgilityPack-PCL
Joon Hong

166

Я не знаю, чи це вам допоможе, але я написав пару статей, в яких знайомиться з основами.

Наступна стаття на 95% завершена, мені просто потрібно написати пояснення останніх кількох частин коду, які я написав. Якщо ви зацікавлені, я спробую запам'ятати публікацію тут, коли публікую її.


16
Нарешті закінчив цю статтю через два роки :) Простий метод виявлення RSS та Atom каналів на веб-сайтах з HtmlAgilityPack
rtpHarry

3
Нещодавно у Code Project вийшла дуже хороша стаття HTMLAgilityPack. Ви можете прочитати його тут
Віктор Зіґлер

64

HtmlAgilityPack використовує синтаксис XPath, і хоча багато хто стверджує, що він погано задокументований, я не мав проблем використовувати його за допомогою цієї документації на XPath: https://www.w3schools.com/xml/xpath_syntax.asp

Проаналізувати

<h2>
  <a href="">Jack</a>
</h2>
<ul>
  <li class="tel">
    <a href="">81 75 53 60</a>
  </li>
</ul>
<h2>
  <a href="">Roy</a>
</h2>
<ul>
  <li class="tel">
    <a href="">44 52 16 87</a>
  </li>
</ul>

Я зробив це:

string url = "http://website.com";
var Webget = new HtmlWeb();
var doc = Webget.Load(url);
foreach (HtmlNode node in doc.DocumentNode.SelectNodes("//h2//a"))
{
  names.Add(node.ChildNodes[0].InnerHtml);
}
foreach (HtmlNode node in doc.DocumentNode.SelectNodes("//li[@class='tel']//a"))
{
  phones.Add(node.ChildNodes[0].InnerHtml);
}

Цілком вірно. Це повністю залежить від XPathстандарту. Спершу слід вивчити цей стандарт, і все буде легко після цього.
FindOut_Quran

Посилання, яке ви надали, більше не доступне. Це, мабуть, нове: w3schools.com/xsl/xpath_syntax.asp
Piotrek

також я не бачу жодної функції SelectNodes () в об'єкті DocumentNode. Перейменовано?
Піотрек

Яку версію ви використовуєте та звідки її завантажили? Відповідно до htmlagilitypack.codeplex.com/SourceControl/latest#Release/1_4_0/… повинен бути метод SelectNodes для класу HtmlNode.
Кент Мунт Касперсен

Посилання недоступне, нове посилання: www.w3schools.com/xml/xpath_syntax.asp
Тирмос

6

Основний код HTMLAgilityPack наступний

using System;
using System.Net;
using System.Web;
using System.Web.Services;
using System.Web.Script.Services;
using System.Text.RegularExpressions;
using HtmlAgilityPack;

namespace GetMetaData
{
    /// <summary>
    /// Summary description for MetaDataWebService
    /// </summary>
    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [System.ComponentModel.ToolboxItem(false)]
    // To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line.
    [System.Web.Script.Services.ScriptService]
    public class MetaDataWebService: System.Web.Services.WebService
    {
        [WebMethod]
        [ScriptMethod(UseHttpGet = false)]
        public MetaData GetMetaData(string url)
        {
            MetaData objMetaData = new MetaData();

            //Get Title
            WebClient client = new WebClient();
            string sourceUrl = client.DownloadString(url);

            objMetaData.PageTitle = Regex.Match(sourceUrl, @
            "\<title\b[^>]*\>\s*(?<Title>[\s\S]*?)\</title\>", RegexOptions.IgnoreCase).Groups["Title"].Value;

            //Method to get Meta Tags
            objMetaData.MetaDescription = GetMetaDescription(url);
            return objMetaData;
        }

        private string GetMetaDescription(string url)
        {
            string description = string.Empty;

            //Get Meta Tags
            var webGet = new HtmlWeb();
            var document = webGet.Load(url);
            var metaTags = document.DocumentNode.SelectNodes("//meta");

            if (metaTags != null)
            {
                foreach(var tag in metaTags)
                {
                    if (tag.Attributes["name"] != null && tag.Attributes["content"] != null && tag.Attributes["name"].Value.ToLower() == "description")
                    {
                        description = tag.Attributes["content"].Value;
                    }
                }
            } 
            else
            {
                description = string.Empty;
            }
            return description;
        }
    }
}

4
Веб-сайт більше не доступний
Димитар Цонев

5
    public string HtmlAgi(string url, string key)
    {

        var Webget = new HtmlWeb();
        var doc = Webget.Load(url);
        HtmlNode ourNode = doc.DocumentNode.SelectSingleNode(string.Format("//meta[@name='{0}']", key));

        if (ourNode != null)
        {


                return ourNode.GetAttributeValue("content", "");

        }
        else
        {
            return "not fount";
        }

    }

0

Початок роботи - HTML Agility Pack

// From File
var doc = new HtmlDocument();
doc.Load(filePath);

// From String
var doc = new HtmlDocument();
doc.LoadHtml(html);

// From Web
var url = "http://html-agility-pack.net/";
var web = new HtmlWeb();
var doc = web.Load(url);

0

спробуйте це

string htmlBody = ParseHmlBody(dtViewDetails.Rows[0]["Body"].ToString());

private string ParseHmlBody(string html)
        {
            string body = string.Empty;
            try
            {
                var htmlDoc = new HtmlDocument();
                htmlDoc.LoadHtml(html);
                var htmlBody = htmlDoc.DocumentNode.SelectSingleNode("//body");
                body = htmlBody.OuterHtml;
            }
            catch (Exception ex)
            {

                dalPendingOrders.LogMessage("Error in ParseHmlBody" + ex.Message);
            }
            return body;
        }
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.