Jak korzystać z pakietu HTML Agility

629

Jak korzystać z pakietu HTML Agility Pack ?

Mój dokument XHTML nie jest w pełni ważny. Dlatego chciałem go użyć. Jak korzystać z niego w moim projekcie? Mój projekt jest w C #.

carla
źródło
79
To pytanie było dla mnie bardzo pomocne.
BigJoe714,
26
Uwaga dodatkowa: w Visual Studio, które obsługuje NuGet, możesz teraz kliknąć prawym przyciskiem myszy „References” i wybrać „Manage NuGet Packages ...”, wyszukać „HtmlAgilityPack” i kliknąć „Install”. Następnie zacznij grać z kodem za pomocą instrukcji using / Import.
patridge
Odnośnie powyższego komentarza @patridge: Odkryłem, że muszę usunąć, a następnie ponownie dodać moje odniesienie do HtmlAgilityPack podczas pierwszego pobierania projektu z svn przez ankhsvn.
Andrew Coonce,
14
Każdy, kto patrzy na HTMLAgilityPack, powinien rozważyć CsQuery, jest to znacznie nowsza biblioteka z dużo bardziej nowoczesnym interfejsem z mojego doświadczenia. Na przykład cały kod z pierwszej odpowiedzi można podsumować w CsQuery as var body = CQ.CreateFromFile(filePath)["body"].
Benjamin Gruenbaum
2
@BenjaminGruenbaum: Kciuki za sugestię CsQuery - skonfiguruj w kilka minut, bardzo łatwy w użyciu.
Neolisk

Odpowiedzi:

358

Najpierw zainstaluj pakiet nuget HTMLAgilityPack w swoim projekcie.

Następnie jako przykład:

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

(Uwaga: ten kod jest tylko przykładem i niekoniecznie najlepszym / jedynym podejściem. Nie używaj go na ślepo we własnej aplikacji).

HtmlDocument.Load()Metoda akceptuje również strumień, który jest bardzo przydatny w integracji z innymi klasami zorientowane strumienia w .NET Framework. Chociaż HtmlEntity.DeEntitize()jest inną przydatną metodą poprawnego przetwarzania jednostek HTML. (dzięki Matthew)

HtmlDocumenti HtmlNode są to klasy, z których będziesz najczęściej korzystać. Podobnie jak parser XML, udostępnia metody selectSingleNode i selectNodes, które akceptują wyrażenia XPath.

Zwróć uwagę na HtmlDocument.Option?????? właściwości boolowskie. Kontrolują one, w jaki sposób Loadi LoadXMLmetody będą przetwarzały Twój HTML / XHTML.

Istnieje również skompilowany plik pomocy o nazwie HtmlAgilityPack.chm, który zawiera pełne odwołanie do każdego obiektu. Zwykle znajduje się w folderze podstawowym rozwiązania.

Popiół
źródło
11
Zauważ również, że Load akceptuje parametr Stream, co jest wygodne w wielu sytuacjach. Użyłem go dla strumienia HTTP (WebResponse.GetResponseStream). Inną dobrą metodą, o której należy pamiętać, jest HtmlEntity.DeEntitize (część pakietu HTML Agility Pack). Jest to potrzebne do ręcznego przetwarzania jednostek w niektórych przypadkach.
Matthew Flaschen
1
Uwaga: w najnowszej wersji beta Html Agility Pack (1.4.0 Beta 2 wydanej 3 października 2009) plik pomocy został przeniesiony do osobnego pliku do pobrania z powodu zależności od Sandcastle, DocProject i Visual Studio 2008 SDK.
rtpHarry
SelectSingleNode() wydaje się, że został usunięty jakiś czas temu
Chris S
3
Nie, SelectSingleNode i SelectNodes są zdecydowanie nadal dostępne. Uważam za trochę interesujące, że powinien to być htmlDoc.ParseErrors.Count (), a nie .Count
Mike Blandford
1
@MikeBlandford // Częściowo tak. Wygląda na to, że został usunięty (lub nie istniał od początku) w wersji HtmlAgailityPack w wersji PCL. nuget.org/packages/HtmlAgilityPack-PCL
Joon Hong
166

Nie wiem, czy ci to pomoże, ale napisałem kilka artykułów, które wprowadzają w podstawy.

Następny artykuł jest w 95% kompletny, muszę tylko napisać wyjaśnienia kilku ostatnich fragmentów kodu, który napisałem. Jeśli jesteś zainteresowany, postaram się pamiętać o opublikowaniu tutaj, kiedy go opublikuję.

rtpHarry
źródło
16
W końcu skończyłem ten artykuł dwa lata później :) Prosta metoda wykrywania kanałów RSS i Atom na stronach internetowych z HtmlAgilityPack
rtpHarry
3
Niedawno w Code Project wydano bardzo dobry artykuł HTMLAgilityPack. Możesz go przeczytać tutaj
Victor Sigler,
64

HtmlAgilityPack używa składni XPath i chociaż wielu twierdzi, że jest słabo udokumentowana, nie miałem problemu z użyciem jej przy pomocy tej dokumentacji XPath: https://www.w3schools.com/xml/xpath_syntax.asp

Do analizowania

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

Ja to zrobiłem:

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);
}
Kent Munthe Caspersen
źródło
Całkowita prawda. Jest w pełni zależny od XPathstandardu. Najpierw należy nauczyć się tego standardu, a potem wszystko będzie łatwe.
FindOut_Quran,
Podany przez Ciebie link nie jest już dostępny. To prawdopodobnie nowy: w3schools.com/xsl/xpath_syntax.asp
Piotrek
także nie widzę żadnej funkcji SelectNodes () w obiekcie DocumentNode. Czy to się zmieniło?
Piotrek,
Z jakiej wersji korzystasz i skąd ją pobrałeś? Według htmlagilitypack.codeplex.com/SourceControl/latest#Release/1_4_0/... powinna istnieć metoda SelectNodes w klasie HtmlNode.
Kent Munthe Caspersen
Link niedostępny, nowy link: www.w3schools.com/xml/xpath_syntax.asp
Tyrmos
6

Główny kod związany z HTMLAgilityPack jest następujący

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;
        }
    }
}
kapitanac
źródło
4
Strona nie jest już dostępna
Dimitar Tsonev
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";
        }

    }
ibrahim ozboluk
źródło
0

Pierwsze kroki - pakiet HTML Agility

// 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);
Meysam
źródło
0

Spróbuj tego

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;
        }
PK-1825
źródło