HTML Parsing och Screen Scraping med Simple HTML DOM Library

Om du behöver analysera HTML, är reguljära uttryck inte vägen att gå. I den här handledningen lär du dig hur du använder en öppen källkod, lätt lärd parser, att läsa, ändra och spotta tillbaka HTML från externa källor. Med hjälp av nätnät kan du lära dig hur du får en lista över alla artiklar som publiceras på webbplatsen och visar dem.

Förresten kan du också hitta parsers på Envato Market, som HTML5 Parser.

HTML5 Parser på Envato Market

Steg 1. Framställning

Det första du behöver göra är att hämta en kopia av simpleHTMLdom-biblioteket, tillgängligt fritt från sourceforge.

Det finns flera filer i hämtningen, men den enda du behöver är filen simple_html_dom.php; Resten är exempel och dokumentation.


Steg 2. Parsing Basics

Det här biblioteket är väldigt lätt att använda, men det finns några grunder du bör granska innan du sätter den i aktion.

Laddar HTML

$ html = new simple_html_dom (); // Ladda från en sträng $ html-> load ('

Hej världen!

Var här

'); // Ladda en fil $ html-> load_file ('http://net.tutsplus.com/');

Du kan skapa ditt ursprungliga objekt antingen genom att ladda HTML från en sträng eller från en fil. Ladda en fil kan göras antingen via URL eller via ditt lokala filsystem.

En försiktighetsåtgärd: Metoden load_file () delegerar sitt jobb till PHPs file_get_contents. Om allow_url_fopen inte är satt till true i din php.ini-fil kanske du inte kan öppna en fjärransluten fil på så sätt. Du kan alltid falla tillbaka på CURL-biblioteket för att ladda externa sidor i det här fallet och sedan läsa in dem med metoden load ().

Åtkomst till information

När du har ditt DOM-objekt kan du börja arbeta med det med hjälp av find () och skapa samlingar. En samling är en grupp av objekt som hittas via en väljare - syntaxen är ganska lik jQuery.

  

Hej världen!

Var här.

I det här exemplet HTML kommer vi att titta på hur du får tillgång till informationen i andra stycket, ändra den och sedan utföra resultaten.

# skapa och ladda HTML-inkludera ('simple_html_dom.php'); $ html = new simple_html_dom (); $ HTML-> last ("

Hej världen!

Var här

"); # få ett element som representerar andra stycket $ element = $ html-> hitta (" p "); # ändra det $ element [1] -> innertext. =" och vi är här för att stanna. mata ut det! echo $ html-> save ();

Med metoden find () återges alltid en samling (array) av taggar om du inte anger att du bara vill ha nth barnet, som en andra parameter.

Linjer 2-4: Ladda HTML-filen från en sträng, som förklarats tidigare.

Linje 7: Den här raden hittar alla

taggar i HTML, och returnerar dem som en array. Den första stycket kommer att ha ett index på 0, och efterföljande stycken kommer att indexeras i enlighet därmed.

rad 10: Detta öppnar 2: a objektet i vår samling av stycken (index 1) och lägger till dess innertextattribut. Innertext representerar innehållet mellan taggarna, medan outertext representerar innehållet inklusive taggen. Vi kunde ersätta taggen helt med hjälp av uttext.

Vi ska lägga till ytterligare en rad och ändra klassen av vår andra styckets tagg.

$ element [1] -> class = "class_name"; echo $ html-> save ();

Den resulterande HTML-filen av Spara-kommandot skulle vara:

  

Hej världen!

Vi är här och vi är här för att stanna.

Övriga väljare

Här är några andra exempel på väljare. Om du har använt jQuery, kommer dessa att vara mycket bekanta.

# få den första förekomsten av $ single = $ html-> find ('# foo', 0); # få alla element med $ collection = $ html-> hitta ('. foo'); # få alla ankarkoder på en sida $ collection = $ html-> find ('a'); # få alla ankarkoder som finns inuti H1-taggar $ collection = $ html-> find ('h1 a'); # få alla img-taggar med en titel på 'himom' $ collection = $ html-> hitta ('img [title = himom]');

Det första exemplet är inte helt intuitivt - alla frågor som standard returnerar samlingar, till och med en ID-fråga, som bara skulle returnera ett enda resultat. Men genom att ange den andra parametern säger vi "returnera endast den första delen av denna samling".

Det betyder att $ single är ett enda element, snarare än en rad element med ett objekt.

Resten av exemplen är självförklarande.

Dokumentation

Komplett dokumentation på biblioteket finns på projektdokumentationssidan.


Steg 3. Real World Exempel

För att sätta detta bibliotek i akt, kommer vi att skriva ett snabbt skript för att skrapa innehållet på webbplatsen på Nettuts, och skapa en lista med artiklar som finns på webbplatsen efter titel och beskrivning ... bara som ett exempel. Skrapning är ett knepigt område på webben, och ska inte utföras utan tillstånd.

innefattar ( 'simple_html_dom.php'); $ articles = array (); getArticles ( 'http://net.tutsplus.com/page/76/');

Vi börjar med att inkludera biblioteket och ringa getArticles-funktionen med den sida som vi skulle vilja börja analysera. I det här fallet börjar vi nära slutet och är snäll mot Nettuts server.

Vi förklarar också en global array för att göra det enkelt att samla all artikelinformation på ett ställe. Innan vi börjar analysera, ta en titt på hur en artikel sammanfattning beskrivs på Nettuts+.

Detta representerar ett grundläggande postformat på webbplatsen, inklusive källkodkommentarer. Varför är kommentarerna viktiga? De räknas som noder till parsern.


Steg 4. Starta parsningsfunktionen

funktion getArticles ($ page) global $ articles; $ html = new simple_html_dom (); $ HTML-> load_file ($ sida); //… Mer… 

Vi börjar helt enkelt genom att hävda vår globala, skapa ett nytt simple_html_dom-objekt och ladda sedan sidan vi vill analysera. Den här funktionen kommer att ringa till sig senare, så vi ställer in det för att acceptera webbadressen som en parameter.


Steg 5. Hitta den information vi vill ha

$ items = $ html-> find ('div [class = preview]'); ($ poster som $ post) # memorera kommentarer räknas som noder $ articles [] = array ($ post-> children (3) -> outertext, $ post-> children (6) -> first_child () -> outertext ); 

Detta är köttet i getArticles-funktionen. Det kommer att ta en närmare titt för att verkligen förstå vad som händer.

Linje 1: Skapar en rad element - div s med klassen av förhandsgranskning. Vi har nu en samling artiklar lagrade i $ poster.

Linje 5: $ post hänvisar nu till en enda div av förhandsgranskning av klassen. Om vi ​​tittar på den ursprungliga HTML-filen kan vi se att det tredje barnet är H1 som innehåller artikeltiteln. Vi tar det och tilldelar det till $ artiklar [index] [0].

Kom ihåg att börja vid 0 och att räkna kommentarer när du försöker bestämma det korrekta indexet för en barnnod.

Linje 6: Sjätte barnet på $ post är

. Vi vill ha beskrivningstexten inifrån, så vi tar tag i det första barnets uttext - det här kommer att inkludera stycketiketten. En enda post i artiklar ser så här ut:

$ articles [0] [0] = "Mitt artikelnamn här"; $ articles [0] [1] = "Detta är min artikelbeskrivning"

Steg 6, pagination

Det första vi gör är att bestämma hur du hittar vår nästa sida. På Nettuts + är webbadresserna enkla att räkna ut, men vi kommer att låtsas att de inte är, och får nästa länk via parsing.

Om vi ​​tittar på HTML ser vi följande:

"

Om det finns en nästa sida (och det kommer inte alltid att finnas) hittar vi ett ankare med klassen "nextpostslink". Nu kan informationen användas.

om ($ next = $ html-> find ('a [class = nextpostslink]', 0)) $ URL = $ next-> href; $ HTML-> clear (); unset ($ html); getArticles ($ URL); 

På första raden ser vi om vi kan hitta ett ankar med klassen nextpostslink. Var särskilt märkt med den andra parametern för find (). Detta anger att vi bara vill att det första elementet (index 0) för den hittades samlingen returneras. $ next kommer bara att innehålla ett enda element, snarare än en grupp av element.

Därefter tilldelar vi länkens HREF till variabeln $ URL. Detta är viktigt för att vi ska förstöra HTML-objektet. På grund av en läckage i php5-cirkulärreferenser måste det aktuella simple_html_dom-objektet rensas och avstängas innan en annan skapas. Om du inte gör det kan det leda till att du äter upp allt tillgängligt minne.

Slutligen kallar vi getArticles med webbadressen till nästa sida. Denna rekursion slutar när det inte finns fler sidor att analysera.


Steg 7 Utmatning av resultaten

Först kommer vi att lägga upp några grundläggande stylings. Det här är helt godtyckligt - du kan göra din produktion ser ut men du vill.

#main margin: 80px auto; bredd: 500px;  h1 font: fet 40px / 38px helvetica, verdana, sans-serif; marginal: 0;  h1 a färg: # 600; text-decoration: none;  p bakgrund: #ECECEC; typsnitt: 10px / 14px verdana, sans-serif; marginal: 8px 0 15px; gränsen: 1px #CCC solid; vaddering: 15px;  .item vaddering: 10px; 

Nästa kommer vi att lägga en liten bit av PHP på sidan för att mata ut den tidigare lagrade informationen.

"; echo $ item [0]; echo $ item [1]; echo"
";?>

Slutresultatet är en enda HTML-sida som innehåller alla artiklar, som börjar på den sida som anges av det första getArticles () -samtalet.


Steg 8 Slutsats

Om du analyserar en hel del sidor (t.ex. hela webbplatsen) kan det ta längre tid än den maximala exekveringstiden som din server tillåter. Till exempel kör från min lokala maskin tar det ungefär en sekund per sida (inklusive tid att hämta).

På en webbplats som Nettuts, med en aktuell 78 sidor av handledning, skulle detta gå över en minut.

Denna handledning bör komma igång med HTML-parsning. Det finns andra metoder att arbeta med DOM, inklusive PHP: s inbyggda, vilket gör att du kan arbeta med kraftfulla xpath-selektorer för att hitta element. För enkel användning och snabbstart finner jag det här biblioteket som ett av de bästa. Som avslutande anteckning, kom alltid ihåg att få tillstånd innan du skrapade en webbplats. det här är viktigt. Tack för att du läser!